The problem with using compose or andThen is that they are built into the Function interface, and the type — both the compilation time and the execution types — of the returned Function functions and not the UnaryOperator or subsequence that you defined. For example, suppose that
UnaryOperator<String> a = s -> s + "bar"; UnaryOperator<String> b = s -> s + s;
You might think that we could write
UnaryOperator<String> c = a.compose(b);
but it will not work! Instead, write
Function<String, String> c = a.compose(b);
For this to work, UnaryOperator would have to provide covariant overrides of andThen and compose . (Perhaps this is a bug in the API.) You would do the same in your subinterface. Or, it's simple enough to write lambdas manually. For example,
interface MyOperator extends UnaryOperator<String> { } public static void main(String[] args) { List<MyOperator> list = Arrays.asList(s -> s + "bar", s -> "[" + s + "]", s -> s + s); MyOperator composite = list.stream() .reduce(s -> s, (a, b) -> s -> b.apply(a.apply(s))); System.out.println(composite.apply("foo")); }
Prints [foobar][foobar] . Note that I used a form with two reduce arguments so as not to deal with Optional .
Alternatively, if you do a lot of composition, you can override the methods you need in your own interface. This is not too complicated. They are based on implementations in java.util.Function , but with the specific String type that I used in this example, they replaced generics.
interface MyOperator extends UnaryOperator<String> { static MyOperator identity() { return s -> s; } default MyOperator andThen(MyOperator after) { Objects.requireNonNull(after); return s -> after.apply(this.apply(s)); } default MyOperator compose(MyOperator before) { Objects.requireNonNull(before); return s -> this.apply(before.apply(s)); } }
This will be used as follows:
MyOperator composite = list.stream() .reduce(MyOperator.identity(), (a, b) -> a.andThen(b));
I think that increasing the scope of the interface for writing andThen instead of the nested lambda is a matter of taste.