When computing Cartesian Products using streams, I can produce them in parallel, and consume them in order, which the following code demonstrates:
int min = 0;
int max = 9;
Supplier<IntStream> supplier = () -> IntStream.rangeClosed(min, max).parallel();
supplier.get()
.flatMap(a -> supplier.get().map(b -> a * b))
.forEachOrdered(System.out::println);
This will print everything perfectly in order, now consider the following code where I want to add it to a list, while preserving the order.
int min = 0;
int max = 9;
Supplier<IntStream> supplier = () -> IntStream.rangeClosed(min, max).parallel();
List<Integer> list = supplier.get()
.flatMap(a -> supplier.get().map(b -> a * b))
.boxed()
.collect(Collectors.toList());
list.forEach(System.out::println);
Now it does not print in order!
This is understandable given that I nowhere demand that the order should be preserved.
Now the question: Is there a way to collect()
or is there a Collector
that preserves order?
If our Stream is ordered, it doesn't matter whether our data is being processed sequentially or in parallel; the implementation will maintain the encounter order of the Stream.
parallel whereas you want to process items in order, so you have to ask about ordering. If you have an ordered stream and perform operations which guarantee to maintain the order, it doesn't matter whether the stream is processed in parallel or sequential; the implementation will maintain the order.
To create a parallel stream from another stream, use the parallel() method. To create a parallel stream from a Collection use the parallelStream() method.
When I executed your code, I got the outputs in order. In fact got the same output for both the code. It seems like the Collector
returned from Collectors.toList
is already ordered, as being depicted by following code:
Collector collector = Collectors.toList();
System.out.print(collector.characteristics());
it prints:
[IDENTITY_FINISH]
Since there is no UNORDERED
characteristics set for the collector, it will process the elements in order only, and which is what the behaviour I'm seeing.
In fact this is clearly mentioned in the docs of Collectors.toList()
:
Returns:
aCollector
which collects all the input elements into aList
, in encounter order
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With