.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()
不包含CONCURRENT
或UNORDERED
特性。
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是平行还是顺序无关紧要。