问题描述
我想计算^ b,例如2 ^ 30,
I want to calculate a^b , e.g. 2^30,
public long pow(final int a, final int b)
首先我用这种方式
return LongStream.range(0, b).reduce(1, (acc, x) -> a * acc); // 1073741824
得到了正确的结果。然后我想并行计算它,所以很自然地我把它改为
Got right result. Then I want to calculate it parallelly, so naturally I changed it to
return LongStream.range(0, b).parallel().reduce(1, (acc, x) -> a * acc); // 32
但在这种情况下结果只是 32
。为什么?
but in this case the result is just 32
. Why?
因此支持并行我再次更改
So for supporting parallel I changed it again
return Collections.nCopies(b,a).parallelStream().reduce(1, (acc, x) -> acc * x); // 1073741824
在这种情况下可行。
那么并行
方式有什么问题?
推荐答案
要求提供的函数。您的功能(acc,x) - > a * acc
不符合要求,因此违反了合同。
reduce requires that the supplied function be associative. Your function (acc, x) -> a * acc
does not satisfy the requirement and thus violates the contract.
要关联,该函数必须满足(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
。
To be associative, the function must satisfy (x op y) op z == x op (y op z)
for any x, y and z. But for your function, (x op y) op z = x*a^2
while x op (y op z) = x * a
.
此外,提供给reduce的第一个参数必须是与累加器函数相关的标识。因此任何x的 1 op x == x
都必须如此。但是这也不适用于你的累加器函数,因为 1 op x == a
。
Furthermore, the first parameter supplied to reduce must be an identity with respect to the accumulator function. So it must be true that 1 op x == x
for any x. But that also doesn't hold for your accumulator function since 1 op x == a
.
正确的方法这样做是:
LongStream.range(0, b).map(x -> a).reduce(1, (u, v) -> u * v);
无论流是并行还是顺序,这都可以保证正常工作。
This is guaranteed to work correctly whether the stream is parallel or sequential.
这篇关于当计算a ^ b为什么并行不起作用但parallelStream可以的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!