depending on the situation, one does not lose all the benefits of parallelism by using ForEachOrdered.

Assume that we have something as such:

stringList.parallelStream().map(String::toUpperCase)
                           .forEachOrdered(System.out::println);

In this case, we can guarantee that the ForEachOrdered terminal operation will print out the strings in uppercase in the encounter order but we should not assume that the elements will be passed to the map intermediate operation in the same order they were picked for processing. The map operation will be executed by multiple threads concurrently. So one may still benefit from parallelism but it's just that we’re not leveraging the full potential of parallelism. To conclude, we should use ForEachOrdered when it matters to perform an action in the encounter order of the stream.

edit following your comment:

What happens when you skip map operation? I am more interested in forEachOrdered right after parallelStream()

if you're referring to something as in:

 stringList.parallelStream().forEachOrdered(action);

there is no benefit in doing such thing and I doubt that's what the designers had in mind when they decided to create the method. in such case, it would make more sense to do:

stringList.stream().forEach(action);

to extend on your question "Why would anyone use forEachOrdered with parallel stream if we are losing parallelism", say you wanted to perform an action on each element with respect to the streams encounter order; in such case you will need to use forEachOrdered as the forEach terminal operation is non deterministic when used in parallel hence there is one version for sequential streams and one specifically for parallel streams.

Answer from Ousmane D. on Stack Overflow
🌐
Oracle
docs.oracle.com › javase › tutorial › collections › streams › parallelism.html
Parallelism (The Java™ Tutorials > Collections > Aggregate Operations)
Consequently, when you execute ... pipeline uses the method forEachOrdered, which processes the elements of the stream in the order specified by its source, regardless of whether you executed the stream in serial or parallel....
Top answer
1 of 3
18

depending on the situation, one does not lose all the benefits of parallelism by using ForEachOrdered.

Assume that we have something as such:

stringList.parallelStream().map(String::toUpperCase)
                           .forEachOrdered(System.out::println);

In this case, we can guarantee that the ForEachOrdered terminal operation will print out the strings in uppercase in the encounter order but we should not assume that the elements will be passed to the map intermediate operation in the same order they were picked for processing. The map operation will be executed by multiple threads concurrently. So one may still benefit from parallelism but it's just that we’re not leveraging the full potential of parallelism. To conclude, we should use ForEachOrdered when it matters to perform an action in the encounter order of the stream.

edit following your comment:

What happens when you skip map operation? I am more interested in forEachOrdered right after parallelStream()

if you're referring to something as in:

 stringList.parallelStream().forEachOrdered(action);

there is no benefit in doing such thing and I doubt that's what the designers had in mind when they decided to create the method. in such case, it would make more sense to do:

stringList.stream().forEach(action);

to extend on your question "Why would anyone use forEachOrdered with parallel stream if we are losing parallelism", say you wanted to perform an action on each element with respect to the streams encounter order; in such case you will need to use forEachOrdered as the forEach terminal operation is non deterministic when used in parallel hence there is one version for sequential streams and one specifically for parallel streams.

2 of 3
3

I don't really get the question here. Why? because you simply have no alternative - you have so much data that parallel streams will help you (this still needs to be proven); but yet you still need to preserve the order - thus forEachOrdered. Notice that the documentation says may and not will lose that for sure - you would have to measure and see.

🌐
Medium
medium.com › @AlexanderObregon › javas-stream-foreachordered-explained-170e6a75c235
Java’s Stream.forEachOrdered() Explained | Medium
September 17, 2024 - Parallel streams are designed to process elements concurrently for increased speed, but forEachOrdered() forces the stream to adhere to the encounter order, limiting the level of concurrency.
🌐
Educative
educative.io › answers › what-is-the-foreachordered-method-of-the-stream-interface
What is the forEachOrdered() method of the Stream Interface?
Aggregate operations iterate over and process these substreams in parallel, and then combine the results. When we use forEachOrdered, the elements are looped in the encounter order if the stream has a defined encounter order.
🌐
HowToDoInJava
howtodoinjava.com › home › java 8 › java stream foreachordered()
Java Stream forEachOrdered() with Examples - HowToDoInJava
March 15, 2022 - This behavior is also true for parallel streams as well as sequential streams. We may lose the benefits of parallelism if we use forEachOrdered() with parallel Streams.
🌐
Baeldung
baeldung.com › home › java › java streams › stream ordering in java
Stream Ordering | Baeldung
January 8, 2024 - ForEach and ForEachOrdered may seem to provide the same functionality, but they have one key difference: ForEachOrdered guarantees to maintain the order of the Stream. If we declare a list: List<String> list = Arrays.asList("B", "A", "C", "D", ...
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › stream › Stream.html
Stream (Java Platform SE 8 )
1 month ago - If the action accesses shared state, ... · void forEachOrdered(Consumer<? super T> action) Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order....
Top answer
1 of 4
119
Stream.of("AAA","BBB","CCC").parallel().forEach(s->System.out.println("Output:"+s));
Stream.of("AAA","BBB","CCC").parallel().forEachOrdered(s->System.out.println("Output:"+s));

The second line will always output

Output:AAA
Output:BBB
Output:CCC

whereas the first one is not guaranted since the order is not kept. forEachOrdered will processes the elements of the stream in the order specified by its source, regardless of whether the stream is sequential or parallel.

Quoting from forEach Javadoc:

The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism.

When the forEachOrdered Javadoc states (emphasis mine):

Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order.

2 of 4
41

Although forEach shorter and looks prettier, I'd suggest to use forEachOrdered in every place where order matters to explicitly specify this. For sequential streams the forEach seems to respect the order and even stream API internal code uses forEach (for stream which is known to be sequential) where it's semantically necessary to use forEachOrdered! Nevertheless you may later decide to change your stream to parallel and your code will be broken. Also when you use forEachOrdered the reader of your code sees the message: "the order matters here". Thus it documents your code better.

Note also that for parallel streams the forEach not only executed in non-determenistic order, but you can also have it executed simultaneously in different threads for different elements (which is not possible with forEachOrdered).

Finally both forEach/forEachOrdered are rarely useful. In most of the cases you actually need to produce some result, not just side-effect, thus operations like reduce or collect should be more suitable. Expressing reducing-by-nature operation via forEach is usually considered as a bad style.

Find elsewhere
🌐
ConcretePage
concretepage.com › java › java-8 › java-stream-foreachordered-vs-foreach
Java Stream : forEachOrdered() vs forEach()
The difference between forEachOrdered() ... non-deterministic. In parallel stream forEach() method may not necessarily respect the order whereas forEachOrdered() will always respect the order....
🌐
Rahulsh1
rahulsh1.github.io › ocp-java8 › pages › chapter5.html
Chapter 5. Parallel Streams
The ordering will be totally random here incase of parallel streams. listOfIntegers .parallelStream() .forEach(e -> System.out.print(e + " ")); forEachOrdered-> processes the elements of the stream in the order specified by its source.
🌐
GeeksforGeeks
geeksforgeeks.org › java › parallel-vs-sequential-stream-in-java
Parallel vs Sequential Stream in Java - GeeksforGeeks
July 15, 2025 - // Java code to demonstrate Iterating in // the same order via parallelStream import java.io.*; import java.util.*; import java.util.stream.*; class ParallelStreamWithOrderedIteration { public static void main(String[] args) { // create a list List<String> list = Arrays.asList("Hello ","G", "E", "E", "K", "S!"); // using parallelStream() method for parallel stream list.parallelStream().forEachOrdered(System.out::print); } } Output ·
🌐
Nus-cs2030
nus-cs2030.github.io › 1718-s2 › lec10 › index.html
10. Parallel streams - CS2030 Programming Methodology II
This is because Stream has broken down the numbers into subsequences, and run filter and forEach for each subsequence in parallel. Since there is no coordination among the parallel tasks on the order of the printing, whichever parallel tasks that complete first will output the result to screen first, causing the sequence of numbers to be reordered. If you want to produce the output in the order of input, use forEachOrdered ...
🌐
Benchresources
benchresources.net › home › java › java 8 – stream foreachordered() method
Java 8 - Stream forEachOrdered() method - BenchResources.Net
May 25, 2022 - Names after UPPER CASE conversion" + " in forEachOrdered SEQUENTIAL processing :- \n"); // get start time startLocalDateTime = LocalDateTime.now(); names // original source .stream() // 1. get SEQUENTIAL stream from source .map(name -> name.toUpperCase()) // 2. map intermediate operation .forEachOrdered(System.out::println); // 3. forEachOrdered terminal operation // get end time after sequential processing endLocalDateTime = LocalDateTime.now(); duration = Duration.between(startLocalDateTime, endLocalDateTime); System.out.println("\nTime difference in Milliseconds" + " after SEQUENTIAL processing = " + duration.toMillis() + " ms"); // PARALLEL - convert names to Upper case and print to console System.out.println("\n\n3.
🌐
Medium
hkdemircan.medium.com › java8-concurrency-parallel-stream-88b4aef91a56
Java8 | Concurrency-Parallel Stream | by Hasan Kadir Demircan | Medium
April 7, 2023 - For the exam, you should remember that parallel streams can process results. Independently, although the order of the results cannot be determined ahead of time. Another example is; List<Integer> data = Collections.synchronizedList(new ArrayList<>()); Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8).parallelStream().map(i -> { data.add(i); // // AVOID STATEFUL LAMBDA EXPRESSIONS! return i; }).forEachOrdered(i -> System.out.print(i + " ")); System.out.println()…
🌐
Java Challengers
javachallengers.com › home › java stream parallel foreachordered
Java Stream parallel forEachOrdered
October 22, 2019 - Learn important principles of stream, parallel and forEachOrdered to improve your Java skills! Improve your Java skills by taking this challenger!
🌐
Jminded
jminded.com › java8-foreach-vs-foreachordered
java8 – forEach vs forEachOrdered – Java Minded
With Java8 streams, we take the advantage of parallelism on multi core processor. Java8 has introduced forEach() forEachOrdered() on collections to iterate over a stream of elements, however there is a difference between the two methods. From the forEach Javadoc: The behavior of this operation ...
Top answer
1 of 2
5

You are right in that the guarantees made for the action of forEachOrdered only apply to that action and nothing else. But it’s wrong to assume that this is the same as .sequential().forEach(…).

sequential will turn the entire stream pipeline into sequential mode, thus, the action passed to forEach will be executed by the same thread, but also the preceding peek’s action. For most intermediate operations, the exact placement of parallel or sequential is irrelevant and specifying both makes no sense as only the last one will be relevant.

Also, there is still no guaranty made about the ordering when using forEach, even if it hasn’t any consequences in the current implementation. This is discussed in “Does Stream.forEach respect the encounter order of sequential streams?”

The documentation of Stream.forEachOrdered states:

This operation processes the elements one at a time, in encounter order if one exists. Performing the action for one element happens-before performing the action for subsequent elements, but for any given element, the action may be performed in whatever thread the library chooses.

So the action may get invoked by different threads, as perceivable by Thread.currentThread() but not run concurrently. Further, if the stream has an encounter order, it will get reconstituted at this place. This answer sheds some light one the difference of encounter order and processing order.

2 of 2
4

The #3 code is not conceptually equivalent to #1, because parallel() or sequential() calls affect the whole stream, not just the subsequent operations. So in #3 case the whole procedure will be performed sequentially. Actually #3 case resembles the early design of the Stream API when you actually could change the parallel/sequential mode. This was considered to be unnecessary complication (and actually added problems, see, for example, this discussion) as usually you only need to change mode to make the terminal operation ordered (but not necessarily sequential). So forEachOrdered() was added and parallel()/sequential() semantics was changed to affect the whole stream (see this changeset).

Basically you're right: in parallel stream there's no order guarantee for intermediate operations. If you need to perform them in particular order, you have to use the sequential stream.