Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use an ordered Collector with a parallel stream?

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?

like image 545
skiwi Avatar asked Mar 22 '14 14:03

skiwi


People also ask

Does parallel stream keep 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.

How do you maintain order in parallel 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.

Which method defined by collection is used to obtain a parallel stream?

To create a parallel stream from another stream, use the parallel() method. To create a parallel stream from a Collection use the parallelStream() method.


1 Answers

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:
a Collector which collects all the input elements into a List, in encounter order

like image 139
Rohit Jain Avatar answered Sep 28 '22 11:09

Rohit Jain