Inspired by this question, I started to play with ordered vs unordered streams, parallel vs sequential streams and terminal operations that respect encounter order vs terminal operations that don't respect it.
In one answer to the linked question, a code similar to this one is shown:
List<Integer> ordered = Arrays.asList(
1, 2, 3, 4, 4, 3, 2, 1, 1, 2, 3, 4, 4, 3, 2, 1, 1, 2, 3, 4);
List<Integer> result = new CopyOnWriteArrayList<>();
ordered.parallelStream().forEach(result::add);
System.out.println(ordered);
System.out.println(result);
And the lists are indeed different. The unordered
list even changes from one run to another, showing that the result is actually non-deterministic.
So I created this other example:
CopyOnWriteArrayList<Integer> result2 = ordered.parallelStream()
.unordered()
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
System.out.println(ordered);
System.out.println(result2);
And I expected to see similar results, as the stream is both parallel and unordered (maybe unordered()
is redundant, since it's already parallel). However, the resulting list is ordered, i.e. it's equal to the source list.
So my question is why the collected list is ordered? Does collect
always respect encounter-order, even for parallel, unordered streams? Is it the specific Collectors.toCollection(...)
collector the one that forces encounter-order?