TL;DR
Yes, the order is guaranteed.
Stream.collect() API documentation
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 (see Collector
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?
?
Collectors.toList() API documentation
toList()
's documentation reads:
Returns a Collector
that accumulates the input elements into a new List
. There are no guarantees on the type, mutability, serializability, or thread-safety of the List
returned; if more control over the returned List
is required, use toCollection(Supplier)
.
Returns:
a Collector which collects all the input elements into a List, in encounter order
An operation that works in encounter order operates on the elements in their original order. This overrides parallelness.
?
Implementation code
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));
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.
?
See also: Why parallel stream get collected sequentially in Java 8