.collect是否保证在并行流上排序? [英] Is .collect guaranteed to be ordered on parallel streams?
问题描述
鉴于我有一个字符串列表 List< String>麦克罗公司一直供应
。结果必须按原始线的顺序排列。
我想利用新的并行流。
Given I have a list of Strings List<String> toProcess
. The results have to be in the order the original lines were given.
I want to utilize the new parallel streams.
以下代码保证结果是否与他们的顺序相同在原始列表中?
Does the following code guarantee that the results will be in the same order they were in the original list?
// ["a", "b", "c"]
List<String> toProcess;
// should be ["a", "b", "c"]
List<String> results = toProcess.parallelStream()
.map(s -> s)
.collect(Collectors.toList());
推荐答案
TL; DR
是的,订单有保证。
TL;DR
Yes, the order is guaranteed.
起点是看是什么决定了减少是否并发。 Stream.collect()
的说明如下:
The starting place is to look at what determines whether a reduction is concurrent or not. Stream.collect()
's description says the following:
If the stream is parallel, and the
Collector
is concurrent, and either the stream is unordered or the collector is unordered, then a concurrent reduction will be performed (seeCollector
for details on concurrent reduction.)
满足第一个条件:流是并行的。第二个和第三个怎么样:收藏家
并发和无序?
The first condition is satisfied: the stream is parallel. How about the second and third: is the Collector
concurrent and unordered?
toList()
的文档内容如下:
toList()
's documentation reads:
返回
收集器
,将输入元素累积到新的列表
。返回的List
的类型,可变性,可序列化或线程安全性无法保证;如果需要对返回的List
进行更多控制,请使用toCollection(Supplier)
。
Returns a
Collector
that accumulates the input elements into a newList
. There are no guarantees on the type, mutability, serializability, or thread-safety of theList
returned; if more control over the returnedList
is required, usetoCollection(Supplier)
.
返回:
a收集器将所有输入元素收集到列表中,遇到订单
在遭遇订单按原始顺序对元素进行操作。这会覆盖并行性。
An operation that works in encounter order operates on the elements in their original order. This overrides parallelness.
检查<的执行情况code> Collectors.java 确认 toList()
不包含 CONCURRENT
或 UNORDERED
traits。
Inspecting the implementation of Collectors.java
confirms that toList()
does not include the CONCURRENT
or UNORDERED
traits.
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
特征set,只有一个 IDENTITY_FINISH
特征。 CONCURRENT
和 UNORDERED
不存在,因此减少不能并发。
Notice how the collector has the CH_ID
trait set, which has only the single IDENTITY_FINISH
trait. CONCURRENT
and UNORDERED
are not there, so the reduction cannot be concurrent.
非并发减少意味着,如果流是并行的,则可以并行进行收集,但是它将被拆分为几个线程限制的中间结果,然后进行组合。这样可确保合并结果符合订单。
A non-concurrent reduction means that, if the stream is parallel, collection can proceed in parallel, but it will be split into several thread-confined intermediate results which are then combined. This ensures the combined result is in encounter order.
另请参阅: 为什么在Java 8中按顺序收集并行流
这篇关于.collect是否保证在并行流上排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!