鉴于我有一个字符串列表List<String> toProcess
。结果必须按原始线的顺序排列。
我想利用新的并行流。
以下代码保证,结果的顺序与原始列表中的顺序相同吗?
// ["a", "b", "c"]
List<String> toProcess;
// should be ["a", "b", "c"]
List<String> results = toProcess.parallelStream()
.map(s -> s)
.collect(Collectors.toList());
答案 0 :(得分:49)
是的,订单有保证。
起点是要确定减少是否并发的原因。 Stream.collect()
的描述如下:
如果流是并行的,并且
Collector
是concurrent,并且流是无序的或收集器是unordered,那么将执行并发减少(请参阅{{ 3}}有关并发减少的详细信息。)
满足第一个条件:流是并行的。第二个和第三个怎么样:Collector
并发和无序?
Collector
的文档内容如下:
返回
Collector
,将输入元素累积为新的List
。对List
返回的类型,可变性,可序列性或线程安全性没有任何保证;如果需要对返回的List
进行更多控制,请使用toCollection(Supplier)
。返回:
收集器将所有输入元素收集到List中,遇到顺序
在toList()
中运行的操作以原始顺序对元素进行操作。这取代了并行性
检查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));
注意收集器如何设置CH_ID
特征集,该特征集仅具有单个IDENTITY_FINISH
特征。 <{1}}和CONCURRENT
不存在,因此减少不能同时发生。
非并发减少意味着,如果流是并行的,则集合可以并行进行,但是它将被分成几个线程限制的中间结果,然后进行组合。这确保了组合结果处于相遇状态
另请参阅: encounter order
答案 1 :(得分:6)
您可以保证获得遇到顺序的元素。
返回: 收集器将所有输入元素收集到List中,遇到顺序
有关“遇到订单”一词的更多信息,请参阅java.util.streams summary。
此外,List#spliterator
文档要求List
的所有实现都会生成ORDERED
的分词符:
Spliterator报告Spliterator.SIZED和Spliterator.ORDERED。实施应记录其他特征值的报告。
奇怪的是,虽然List
接口需要iterator()
以“正确的顺序”生成元素,但spliterator()
只需要排序,但不是特别要求遵循列表的自然顺序。
因此,为了回答您的问题,toList
生成的列表保证包含与源列表的分裂器命令它们完全相同的元素。流是并行还是顺序无关紧要。