TL;DR
是的,订单有保证。
Stream.collect() API 文档
开始的地方是看看是什么决定了减少是否是并发的。 Stream.collect() 的描述如下:
如果流是并行的,并且Collector 是concurrent,并且流是无序的或者收集器是unordered,则将执行并发归约(有关并发归约的详细信息,请参阅Collector .)
满足第一个条件:流是并行的。第二个和第三个呢:Collector是并发无序的吗?
Collectors.toList() API 文档
toList() 的文档内容如下:
返回一个Collector,它将输入元素累积到一个新的List中。不保证返回的List 的类型、可变性、可序列化性或线程安全性;如果需要对返回的List 进行更多控制,请使用toCollection(Supplier)。
返回:
一个收集器,将所有输入元素收集到一个列表中,按遇到顺序
在encounter order 中有效的操作以原始顺序对元素进行操作。这会覆盖并行性。
实现代码
检查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 特征。 CONCURRENT 和 UNORDERED 不存在,因此减少不能并发。
非并发归约意味着,如果流是并行的,则收集可以并行进行,但它将被拆分为几个线程限制的中间结果,然后将它们组合起来。这可确保组合结果按遇到顺序排列。
另请参阅: Why parallel stream get collected sequentially in Java 8