简体   繁体   中英

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?

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?

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.

Stream pipelines may execute either sequentially or in parallel. This execution mode is a property of the stream. Streams are created with an initial choice of sequential or parallel execution. For example, Collection.stream() creates a sequential stream, and Collection.parallelStream() creates a parallel one. This choice of execution mode may be modified by the BaseStream.sequential() or BaseStream.parallel() methods.

So there is no need to use:

listOfIntegers.parallelStream().sequential()

You can only use:

listOfIntegers.stream()

If you are creating a parallel stream , it is possible for the elements of the stream to be processed by different threads. The difference between forEach and forEachOrdered is that forEach will allow any element of a parallel stream to be processed in any order, while forEachOrdered will always process the elements of a parallel stream in the order of their appearance in the original stream. When using parallelStream() and forEachOrdered is a very good example on how you can take advantage of multiple cores and still preserve the order of the output. Note that forEachOrdered forces the iteration of the elements of the stream in an ordered fashion. However, any operation that is chained before forEachOrdered will still happen in parallel because the stream is a parallel stream.

It is not documented by Oracle exactly what happens when you change the stream execution mode multiple times in a pipeline. It is not clear whether it is the last change that matters or whether operations invoked after calling parallel() can be executed in parallel and operations invoked after calling sequential() will be executed sequentially.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM