Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between forEachOrdered() and sequential() methods of Java 8?

I am working on java 8 parallel stream and wanting to print the elements in parallel stream is some order (say insertion order, reverse order or sequential order).

For which i tried the following code:

        System.out.println("With forEachOrdered:");
        listOfIntegers
            .parallelStream()
            .forEachOrdered(e -> System.out.print(e + " "));
        System.out.println("");

        System.out.println("With Sequential:");
        listOfIntegers.parallelStream()
                    .sequential()
                    .forEach(e -> System.out.print(e + " "));

And for both of these, i got the same output as follows:

With forEachOrdered:
1 2 3 4 5 6 7 8 
With Sequential:
1 2 3 4 5 6 7 8 

from the api documentation, i can see that:

forEachOrdered -> This is a terminal operation.

and

sequential -> This is an intermediate operation.

So my question is which one is more better to use? and in which scenarios, one should be preferred over other?

like image 398
KayV Avatar asked Dec 14 '17 07:12

KayV


People also ask

What is forEachOrdered in Java?

The Stream forEachOrdered() method is used to iterate over all the elements of the given Stream and to perform a Consumer action on each element of the Stream, in the encounter order of the Stream if the Stream has a defined encounter order.

What is the correct difference between parallel stream and sequential stream?

In the case of a sequential stream, the content of the list is printed in an ordered sequence. The output of the parallel stream, on the other hand, is unordered and the sequence changes every time the program is run. This signifies at least one thing: that invocation of the list.

What is the difference between stream () and Parallelstream ()?

A sequential stream is executed in a single thread running on one CPU core. The elements in the stream are processed sequentially in a single pass by the stream operations that are executed in the same thread. A parallel stream is executed by different threads, running on multiple CPU cores in a computer.


2 Answers

listOfIntegers.parallelStream().sequential().forEach() creates a parallel Stream and then converts it to a sequential Stream, so you might as well use listOfIntegers.stream().forEach() instead, and get a sequential Stream in the first place.

listOfIntegers.parallelStream().forEachOrdered(e -> System.out.print(e + " ")) performs the operation on a parallel Stream, but guarantees the elements will be consumed in the encounter order of the Stream (if the Stream has a defined encounter order). However, it can be executed on multiple threads.

I don't see a reason of ever using listOfIntegers.parallelStream().sequential(). If you want a sequential Stream, why create a parallel Stream first?

like image 193
Eran Avatar answered Nov 09 '22 22:11

Eran


You are asking somehow a misleading question, first you ask about:

 .parallelStream()
 .forEachOrdered(...)

This will create a parallel Stream, but elements will be consumed in order. If you add a map operation like this:

.map(...)
.parallelStream()
.forEachOrdered(...)

This will make the map very limited (from a parallel processing point of view) operations since threads have to wait for all other elements in encounter order to be processed (consumed by forEachOrdered). This regards stateless operations.

On the other hand if you have a stateful operation like:

.parallelStream()
.map()
.sorted()
.// other operations

Since sorted is stateful, the benefit of the stateless operations before it from a parallel processing will be bigger. And that happens because sorted has to gather all elements from the Stream, and Threads don't have to "wait" (at the forEachOrdered) for the elements in encounter order.

For the second example:

listOfIntegers.parallelStream()
                .sequential()
                .forEach(e -> System.out.print(e + " "))

you are basically saying turn parallel on and then turn it off. Streams are driven by the terminal operation, so even if you do:

 .map...
 .filter...
 .parallel()
 .map...
 .sequential

This means that the entire pipeline will be executed sequentially, not that some part will be parallel and the other sequential. You are also relying on the fact that forEach preserves order and may be at the moment it does, but may be in a later release, sine you said you don't care about order (by using forEach in the first place), there will be an internal shuffling of the elements.

like image 37
Eugene Avatar answered Nov 09 '22 23:11

Eugene