用Java 8 Streams替换传统的newForLoop

gab*_*zou 8 java foreach lambda java-8 java-stream

所以,最后从Java 6跳到Java 8,我已经阅读了相当数量的Java 8 Streams API.不幸的是,几乎所有被问到的例子几乎都接近于我想要弄清楚怎么做,但还不够接近.

我拥有的是什么

final List<Function<? super Double, Double>> myList = generateList();
final double myVal = calculate(10);

private double calculate(double val) {
    for (Function<? super Double, Double> function : this.myList) {
        val += function.apply(val);
    }
    return val;
}
Run Code Online (Sandbox Code Playgroud)

现在,我已经明白我可以做类似的事情.stream().forEach(),但只适用于foreach和stream需要最终变量.我试图探索一下DoubleStream得到一个sum(),但我需要重新应用当前的和每个Function并将该总和添加到下一个函数,如上面的代码示例所示.

纯流API可以实现这一点吗?

编辑:因此,在对该reduce()区域进行测试后,我对执行此类计算所花费的时间进行了简单测试,结果不支持流.这是一个示例https://gist.github.com/gabizou/33f616c08bde5ab97e56.包括来自相当基本测试的日志输出.

Hol*_*ger 10

您可以使用流API从函数列表中组合函数.

static List<Function<? super Double, Double>> myList
    = Arrays.asList(d -> d + 4, d -> d * 2, d -> d - 3);

static Function<Double, Double> total=myList.stream()
    .map(f -> (Function<Double, Double>) d -> d + f.apply(d))
    .reduce(Function::andThen).orElse(Function.identity());

static double calculate(double val) {
    return total.apply(val);
}

public static void main(String[] args) {
    System.out.println(calculate(10));
}
Run Code Online (Sandbox Code Playgroud)

产生组合函数的流操作没有关联性问题,理论上甚至可以并行运行(虽然这里没有任何好处),而结果是一个单独的函数,它本身是顺序的,永远不会溶解成需要的部分.是联想的.

  • @RealSkeptic:问题是lambda表达式产生了新的类,它们将合成方法调用回定义类.在未完全初始化的类上执行的异步方法调用将等待初始化的完成,因此如果初始化程序本身等待该异步操作的完成,则您具有死锁.因此,"静态"初始化器中的并行流操作是不可行的. (2认同)
  • @Leonardo Pina:作曲不像`f(x)+g(x)+h(x)`,而是像`h(g(f(x)))`,即一个函数的输出是下一个。在这种特殊情况下,每个函数 `f` 被投影到 `x+f(x)`,因此,结果函数类似于 `h(g(f(x)+x)+f(x)+x)+ g(f(x)+x)+f(x)+x`。这也是问题的循环正在做的事情;它将函数的结果添加到 `val`,但 `val` 是下一个函数的参数。 (2认同)