在Java8中减少UnaryOperators列表的首选方法是什么,直到它们表示我可以调用apply的一个UnaryOperator?例如,我有以下内容
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);
}但是这段代码会在(MyFilter)f1.andThen(f2)上抛出一个(MyFilter)f1.andThen(f2)。我真的想要这个代码的效果在最后:
MyObject o = obj;
for(MyFilter f:filters){
o = f.apply(o);
}
return o;但我也很好奇如何使用compose或andThen将一个函数集合简化为一个函数。
发布于 2014-06-03 03:57:39
使用compose或andThen的问题是,它们内置到Function接口中,它们返回的函数的类型--编译时类型和运行时类型--是Function,而不是UnaryOperator或您定义的子接口。例如,假设我们有
UnaryOperator<String> a = s -> s + "bar";
UnaryOperator<String> b = s -> s + s;有人可能会认为我们可以写
UnaryOperator<String> c = a.compose(b);但这不管用!相反,一个人必须写
Function<String, String> c = a.compose(b);为此,UnaryOperator必须提供andThen和compose的协变量重写。(可以说这是API中的一个bug。)你也会在你的子界面上做同样的事情。或者,用手把兰巴达写出来就够简单了。例如,
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"));
}这个打印出了[foobar][foobar]。请注意,为了避免不得不处理reduce,我使用了双arg形式的Optional。
或者,如果您经常进行函数组合,则可以在您自己的接口中重新实现所需的方法。不太难。这些是基于java.util.Function中的实现,但是我在本例中使用的具体String类型代替了泛型。
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));
}
}这将用于以下方面:
MyOperator composite =
list.stream()
.reduce(MyOperator.identity(), (a, b) -> a.andThen(b));我想,用扩展接口来编写andThen而不是嵌套的lambda是否是一个品味问题。
https://stackoverflow.com/questions/24006489
复制相似问题