Stream reduce vs Stream.parallel.reduce()

E2r*_*abi 4 java collections reduce java-8 java-stream

我试图理解为什么这个例子的结果总是如此,这是我的例子:

 String s1 = Arrays.asList("A", "E", "I", "O", "U").stream()
                .reduce("", String::concat);
 String s2 = Arrays.asList("A", "E", "I", "O", "U").parallelStream()
                .reduce("", String::concat);

System.out.println(s1.equals(s2));
Run Code Online (Sandbox Code Playgroud)

这总是打印true,我所知道的是使用 parallelStream 我们无法预测结果有人可以解释为什么吗?

Sam*_*ipp 5

如果你看一下你的文档,Stream.reduce()你会发现:

对此流 [...] 的元素执行缩减并返回缩减后的值。这相当于:

 T result = identity;
 for (T element : this stream)
     result = accumulator.apply(result, element)
 return result;
Run Code Online (Sandbox Code Playgroud)

但不限于顺序执行。

因此Stream.reduce()确保按顺序处理值。

如果您尝试使用Stream.forEach()和打印每个值,如下所示:

Arrays.asList("A", "E", "I", "O", "U").stream()
        .forEach(System.out::print);
System.out.println();
Arrays.asList("A", "E", "I", "O", "U").parallelStream()
        .forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)

您将得到以下结果(或第二行中的类似结果):

AEIOU
IUOEA
Run Code Online (Sandbox Code Playgroud)

Stream.forEachOrdered()上面的例子也将按顺序打印值)

  • 这里同样重要的一点是,“String::concat”是*关联的*(因此对于函数“fun”,“(a fun b) fun c == a fun (b fun c)”总是正确的)。如果累加器双功能不具有关联性,我们将不会得到正确的结果。例如,使用累加器函数“(a,b) -> ab”减少包含“1,2,3,4”的流,而不是像“(((1-2)-3)-4) = -8”那样执行在并行处理中可以像“(1-2)-(3-4) = (-1) - (-1) = 0”一样执行。演示:https://ideone.com/wUWknA (3认同)