Java Stream更新运行总计

时间:2017-01-06 19:25:41

标签: java-8 java-stream

我有以下java行代码,我想知道它是否可以完全转换为Java 8 Stream时尚?

long totalSum = list.parallelStream().mapToLong(ExpenseInfo::getCurrCount).sum();

// LOOP ALL COLLECTION
for (ExpenseInfo info : list) {
    totalSum -= info.getCurrCount();
    info.setBurnCount(totalSum);
}

1 个答案:

答案 0 :(得分:2)

问题是默认情况下你的任务是顺序的。例如,第一个元素的刻录计数设置为总和减去它自己的计数,而第二个元素的刻录计数设置为总和减去它自己的计数和前面元素的计数,依此类推。 / p>

也就是说,如果您必须使用流来转换此指令序列并且流将是并行的(使用.stream().parallelStream()应该对您计算的结果没有影响), totalSum变量将被共享,并且有序流中的每个元素都必须等待每个前一个元素计算的总和的更新值,这将完全打败使用并行性的目的。

也就是说,您可以使用另一种方法,首先将每个实例映射到其自己的curr计数,然后使用Arrays.parallelPrefix计算累积的数量到一个数组。

最后,您可以使用IntStream通过减去该元素的总和和累计总和来设置每个元素的毛刺数。

long[] sums = list.stream().mapToLong(ExpenseInfo::getCurrCount).toArray();
Arrays.parallelPrefix(sums, Long::sum);
IntStream.range(0, sums.length).forEach(i -> list.get(i).setBurnCount(sums[sums.length - 1] - sums[i]));

当然,它假设列表是随机访问,因此get(int i)不是一项昂贵的操作,但所有内容都可以并行化而没有问题(实际上parallelPrefix已经并行化了,顾名思义)。

我仍然会把你的方法放在第一位,对我来说似乎更清楚。