减少 Java 8 中的 UnaryOperator 列表直到它们代表一个我可以调用 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)
处抛出一个 ClassCastException
。
非常想要这段代码最后的效果:
MyObject o = obj;
for(MyFilter f:filters){
o = f.apply(o);
}
return o;
但我也很好奇我们如何使用 compose
或 andThen
将一组函数简化为一个函数。
最佳答案
使用 compose
或 andThen
的问题是它们内置于 Function
接口(interface)和类型中——都是编译时的和运行时类型——它们返回的函数是 Function
而不是 UnaryOperator
或您定义的子接口(interface)。例如,假设我们有
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 中的错误。)您可以在子界面中执行相同的操作。或者,手写 lambda 就足够简单了。例如,
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
的双参数形式以避免必须处理 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 而增加接口(interface)是一个品味问题。
关于java - 减少 Java 8 中的 UnaryOperators 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24006489/