使用Java8流api将函数列表应用于值

ver*_*tti 6 java reduce java-8

我想要一个单独的日志消息pojo LoggedExchange并应用一堆转换.转换是列表中的UnaryOperators:

List<ConditionalTransform> transforms = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

其中,ConditionalTransform农具UnaryOperator<LoggedExchange>和我目前的解决方案是使用减少这样的:

public LoggedExchange transform(LoggedExchange original) {
    return transforms.stream().reduce(original, (o, t) -> t.apply(o), (m1, m2) -> m2);
}
Run Code Online (Sandbox Code Playgroud)

并行运行这个没有意义,因为没有办法将两个消息组合在一起((m1,m2) -> m2只是为了让编译器满意).

有没有更好的方法来做到这一点(就像以某种方式组成所有ConditionalTranforms?),如果没有,该combiner函数是否会抛出异常或其他因为我不能支持并行执行?

JavaDoc中指出,大多数这些操作有可能需要做mapreduce,但我看不出如何.

use*_*751 7

这样的事情应该有效:

public LoggedExchange transform(LoggedExchange original) {
    return transforms.stream().reduce(UnaryOperator.identity(), (a, b) -> ((LoggedExchange o) -> b.apply(a.apply(o)))).apply(original);
}
Run Code Online (Sandbox Code Playgroud)

这构造了一个单独依次UnaryOperator<LoggedExchange>应用所有函数transforms,然后用输入值调用它.

或者,总是有简单的循环版本:

public LoggedExchange transform(LoggedExchange value) {
    for(UnaryOperator<LoggedExchange> transform : transforms)
        value = transform.apply(value);
    return value;
}
Run Code Online (Sandbox Code Playgroud)

  • 注意:如果`transforms`是`Collection <Function <LoggedExchange,LoggedExchange >>`那么你可以使用`.reduce(Function.identity(),Function :: andThen)`.(如果它是`Collection <UnaryOperator <LoggedExchange >>`并且你这样做,那么类型推断失败,即使`UnaryOperator <T>`扩展`Function <T,T>`) (2认同)