2014-12-23 21 views
2

我有以下列表integers(所有的数字从0到999,999):为什么顺序流和并行流的缩减结果不同?

List<Integer> integers = new ArrayList<>(); 
for (int i = 0; i != 10_000_000; ++i) { 
    integers.add(i); 
} 

我试图运行下面作为Java 8个流:

int sum = 0; 
for (Integer i : integers) { 
    sum = i % 2 == 0 ? i - sum : i + sum; 
} 
System.out.println(sum); 

我期待下面的输出:

0 - 0 = 0 
1 + 0 = 1 
2 - 1 = 1 
3 + 1 = 4 
4 - 4 = 0 
5 + 0 = 5 
6 - 5 = 1 
7 + 1 = 8 
8 - 8 = 0 
... 
999,998 - 999,997 = 1 
999,999 + 1 = 10,000,000 

10,000,000(顺便说一句,有人可以也许数学表达这个我不能......?)

如果我运行此:

int sum = integers.stream().reduce(
       0, 
       (sum, i) -> i % 2 == 0 ? i - sum : i + sum 
      ); 

sum是预期的量,10,000,000

但是,如果我改变流平行:

int sum = integers.parallelStream().reduce(
       0, 
       (sum, i) -> i % 2 == 0 ? i - sum : i + sum 
      ); 

sum0

我似乎无法弄清楚为什么是这种情况,有人可以解释这一点吗?

+0

这对我来说仍然很有趣**为什么**它总是** 0。 –

回答

6

Javadoc文档reduce

执行这个流的元素的减少,使用关联累积功能,

注意单词“联想”:这是一个属性您减少功能不具备。

关联性是并行化的关键:操作的应用顺序没有定义,没有关联性,结果在重新排序时不会不变。

如果你有两个以上的availableProcessors,你可以使用下面的代码来说服你自己,答案取决于子任务的数量(注意,你不应该使用10_000_000作为问题的大小,因为它有很多两个在其分解;使用10_000_001):

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "2"); 
System.out.println(IntStream.range(0,10_000_001).parallel().reduce(0, 
    (sum, i) -> i % 2 == 0 ? i - sum : i + sum 
)); 

当您更改系统属性值,结果也会改变。

相关问题