为什么组合器不会在stream.reduce中调用,尽管结果是正确的

时间:2015-09-26 14:07:12

标签: java java-8 java-stream reduce

我编写了以下代码示例来计算流中的总字符串长度:

/src/main/webapp/WEB-INF/jsp/welcome.jsp

我看到以下输出:

Integer reduce = Stream.of("AAA", "BBB", "CCC")
            .reduce(0, (result, s) -> {
                System.out.println("#accumulator# " + s);
                return result + s.length();
            }, (integer, integer2) -> {
                System.out
                        .println("#combiner#" + "integer: " + integer + "integer2:" + integer2);
                return integer + integer2;
            });
    System.out.println(reduce);

正如你所看到的,我得到了正确的结果,但组合器永远不会调用。

为什么呢?这是如何工作的?

请解释概念。

2 个答案:

答案 0 :(得分:3)

Stream.reduce中的组合器参数实际上仅在并行Stream的情况下被调用。这是因为当流并行执行时,Java会将流分区为多个子流。聚合操作迭代并并行处理这些子流,然后合并结果。

通过调用parallel()更改您的代码以使用并行流,您将看到组合器被调用。

在此方法的Javadoc中,您可以看到等效代码中不存在combiner

  

这相当于:

U result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;

答案 1 :(得分:2)

TL; DR:为并行Streams 调用组合器。

Spliteratorsplit()时,会在两个不同的Thread处理时调用合并函数,并且需要合并结果。由于Stream不是parallel,因此不需要此功能。

顺便提一下,您的代码更好地写为:

final int total = Stream.of("AAA", "BBB", "CCC")
                        .mapToInt(String::length)
                        .sum();