zhu*_*wei 3 java parallel-processing reduce java-8 java-stream
我想计算一个^ b,例如2 ^ 30,
public long pow(final int a, final int b)
Run Code Online (Sandbox Code Playgroud)
首先我用这种方式
return LongStream.range(0, b).reduce(1, (acc, x) -> a * acc); // 1073741824
Run Code Online (Sandbox Code Playgroud)
得到正确的结果.然后我想要平行计算它,所以我自然而然地将它改为
return LongStream.range(0, b).parallel().reduce(1, (acc, x) -> a * acc); // 32
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,结果就是32.为什么?
所以为了支持并行我再次改变它
return Collections.nCopies(b,a).parallelStream().reduce(1, (acc, x) -> acc * x); // 1073741824
Run Code Online (Sandbox Code Playgroud)
在这种情况下它有效.
那方式有什么问题parallel?
reduce要求提供的函数是关联的.您的功能(acc, x) -> a * acc不符合要求,因此违反了合同.
要进行关联,函数必须满足(x op y) op z == x op (y op z)任何x,y和z.但是对于你的功能,(x op y) op z = x*a^2同时x op (y op z) = x * a.
此外,提供给reduce的第一个参数必须是与累加器函数相关的标识.所以1 op x == x对于任何x都必须如此.但是那也不适用于你的累加器功能1 op x == a.
正确的方法是:
LongStream.range(0, b).map(x -> a).reduce(1, (u, v) -> u * v);
Run Code Online (Sandbox Code Playgroud)
无论流是并行还是顺序,这都可以保证正常工作.