.collect是否保证在并行stream上sorting?

鉴于我有一个stringList<String> toProcess 。 结果必须按原始顺序排列。 我想利用新的并行stream。

以下代码是否保证结果与原始列表中的顺序相同?

 // ["a", "b", "c"] List<String> toProcess; // should be ["a", "b", "c"] List<String> results = toProcess.parallelStream() .map(s -> s) .collect(Collectors.toList()); 

TL; DR

是的,订单是有保证的。

Stream.collect()API文档

开始的地方是看是什么决定是否减less并发与否。 Stream.collect()的描述如下:

如果stream是并行的,并且Collector是并发的 ,并且stream是无序的或者收集器是无序的 ,那么将执行并发的减less(参见Collector以获得并发减less的细节)。

第一个条件是满足的:stream是平行的。 第二个和第三个: Collector并发的还是无序的?

Collectors.toList()API文档

toList()的文档如下所示:

返回将input元素累加到新List中的Collector 。 对返回的List的types,可变性,可串行性或线程安全性没有保证; 如果需要更多的对返回List控制,请使用toCollection(Supplier)

返回:
一个收集器,将所有的input元素按照遇到的顺序收集到一个列表

在遇到顺序中运行的操作按照原始顺序对元素进行操作。 这覆盖了并行性。

执行代码

检查Collectors.java的实现证实toList()不包含CONCURRENTUNORDERED特性。

 public static <T> Collector<T, ?, List<T>> toList() { return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left; }, CH_ID); } // ... static final Set<Collector.Characteristics> CH_ID = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH)); 

请注意collections家是如何设置CH_ID特征的,它只有单一的IDENTITY_FINISH特征。 不存在并发和不和,所以减less不能并发。

非并行约简意味着,如果stream是并行的,那么可以并行地进行收集,但是它将被分割成几个线程约束的中间结果,然后这些结果被组合。 这确保了结合的结果在遇到顺序。

另请参阅: 为什么并行stream在Java 8中按顺序收集

你保证得到遇到顺序的元素。

toList文档 :

返回:一个收集器, 按照遇到的顺序将所有的input元素收集到一个List

有关术语“遇到命令”的更多信息,请参阅java.util.streams摘要 。

此外, List#spliterator文档要求List#spliterator的所有实现产生ORDERED分割器:

Spliterator报告Spliterator.SIZED和Spliterator.ORDERED。 实现应logging附加特征值的报告。

奇怪的是,尽pipeList接口需要iterator()以“正确的顺序”产生元素, spliterator()只需要sorting,但并不需要遵循列表的自然sorting。

因此,为了回答你的问题, toList生成的列表保证包含与源列表的分割器命令一样的元素。 stream是平行还是顺序无关紧要。