Is it possible to use an ordered collector with a parallel flow?

When computing Cartesian products using streams, I can produce them in parallel and consume them in order, as 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 completely print everything in order, now consider the following code, where I want to add it to the list, while maintaining 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 do not demand anywhere to maintain order.

Now the question is: is there a way to collect() or is there a Collector that preserves order?

+6
source share
1 answer

When I executed your code, I got the results in order. Actually got the same result for both codes. It appears that Collector returned from Collectors.toList is already ordered, as shown by the following code:

 Collector collector = Collectors.toList(); System.out.print(collector.characteristics()); 

he prints:

 [IDENTITY_FINISH] 

Since there are no UNORDERED characteristics for the collector, it will only process elements in order, and this is exactly the behavior I see.

In fact, this is clearly stated in the Collectors.toList() docs:

Return:
a Collector that collects all the input elements in a List , in order of execution

+4
source

All Articles