小编典典

为什么在Java 8中按顺序收集并行流

java

为什么总是forEach以随机顺序打印数字,而collect始终从原始顺序收集元素,即使是从并行流中呢?

Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8};
List<Integer> listOfIntegers = new ArrayList<>(Arrays.asList(intArray));

System.out.println("Parallel Stream: ");
listOfIntegers
  .stream()
  .parallel()
  .forEach(e -> System.out.print(e + " "));
System.out.println();

// Collectors         
List<Integer> l = listOfIntegers
  .stream()
  .parallel()
  .collect(Collectors.toList());
System.out.println(l);

输出:

Parallel Stream: 
8 1 6 2 7 4 5 3 
[1, 2, 3, 4, 5, 6, 7, 8]

阅读 225

收藏
2020-09-11

共1个答案

小编典典

这里有两种不同的“排序”,使讨论变得混乱。

一种是 遇到顺序 ,该 顺序
流文档中定义。考虑这一点的一种好方法是源集合中元素的 空间 顺序或 从左到右的
顺序。如果源是List,请考虑将较早的元素放在较后的元素的左侧。

还有文档中未定义的 处理时间
顺序,但这是由不同线程处理元素的时间顺序。如果列表的元素由不同的线程并行处理,则线程可能在列表中最右边的元素之前处理最右边的元素。但是下次可能不会。

即使并行执行计算,大多数Collectors和某些终端操作也会精心安排,以便它们保留从源到目的地的 遇到 顺序 ,而与不同线程处理每个元素的
时间顺序 无关。

需要注意的是,forEach终端的操作并 不能
保留相遇秩序。相反,它由发生任何下一个结果的线程运行。如果您想要这样的东西forEach来保留相遇顺序,请forEachOrdered改用。

另请参阅Lambda常见问题解答,以进一步了解订购问题。

2020-09-11