functional programming - Reducing a list of UnaryOperators in Java 8 -
what preferred way of reducing list of unaryoperators in java 8 till represent 1 unaryoperator can call apply on? example have following
interface myfilter extends unaryoperator<myobject>{}; public myobject filterit(list<myfilter> filters,myobject obj){ optional<myfilter> mf = filters .stream() .reduce( (f1,f2)->(myfilter)f1.andthen(f2)); return mf.map(f->f.apply(obj)).orelse(obj); }
but code throws classcastexception
@ (myfilter)f1.andthen(f2)
. want effect of code in end:
myobject o = obj; for(myfilter f:filters){ o = f.apply(o); } return o;
but curious of how can reduce collection of functions 1 function, using compose
or andthen
.
the problem using compose
or andthen
they're built function
interface , type -- both compile-time , runtime types -- of functions return function
, not unaryoperator
or subinterface such you've defined. example, suppose have
unaryoperator<string> = s -> s + "bar"; unaryoperator<string> b = s -> s + s;
one might think write
unaryoperator<string> c = a.compose(b);
but doesn't work! instead, 1 has write
function<string, string> c = a.compose(b);
for work, unaryoperator
have provide covariant overrides of andthen
, compose
. (arguably bug in api.) you'd same in subinterface. or, it's simple enough write out lambdas hand. 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")); }
this prints out [foobar][foobar]
. note i've used two-arg form of reduce
in order avoid having deal optional
.
alternatively, if you're doing function composition lot, reimplement methods need in own interface. it's not hard. these based on implementations in java.util.function
concrete string
type i've been using in example substituted 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 used follows:
myoperator composite = list.stream() .reduce(myoperator.identity(), (a, b) -> a.andthen(b));
whether bulking interface in order write andthen
instead of nested lambda matter of taste, guess.
Comments
Post a Comment