java - 减少 Java 8 中的 UnaryOperators 列表

标签 java functional-programming java-8

减少 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;

但我也很好奇我们如何使用 composeandThen 将一组函数简化为一个函数。

最佳答案

使用 composeandThen 的问题是它们内置于 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 必须提供 andThencompose 的协变覆盖。 (可以说这是 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/

相关文章:

Java8 lambda 将 List 转换为 Map of Maps

Java:为什么我的break语句不起作用?

java - 有没有办法部分控制Java并行流的顺序?

java - Comparator.nullsLast 不会避免 NullPointerException

android - 使用 RxJava Async 时的循环推理

java - 用自己的实现和信任管理器替换默认的 SSLContext

java - 从sqlite数据库java中检索图像

f# - F#中的异步屏障

python - 使用 map-reduce/itertools 对嵌套迭代求和

scala - Kestrel 函数式编程设计模式的附加值(value)是什么? (斯卡拉)