Let’s break down the difference between forEach()
and forEachOrdered()
— two commonly used terminal operations in Java Streams.
✅ 1. forEach()
📌 Definition:
void forEach(Consumer<? super T> action)
Applies a given action to each element of the stream
Order is not guaranteed, especially when using parallel streams
🧠 Example:
Stream.of("A", "B", "C")
.forEach(System.out::print); // Output: ABC (but order is not guaranteed in parallel)
⚠️ In a parallel stream:
Stream.of("A", "B", "C").parallel()
.forEach(System.out::print); // Output may be: BCA, CAB, etc.
✅ 2. forEachOrdered()
📌 Definition:
void forEachOrdered(Consumer<? super T> action)
Applies the action to each element in the encounter order
Maintains the order, even in parallel streams
May have lower performance in parallel streams because it has to preserve ordering
🧠 Example:
Stream.of("A", "B", "C").parallel()
.forEachOrdered(System.out::print); // Output: ABC (always)
🔁 Comparison Table
Feature | forEach() | forEachOrdered() |
---|---|---|
🔁 Stream type | Works on sequential & parallel | Works on sequential & parallel |
🔃 Order preserved? | ❌ No (especially in parallel) | ✅ Yes — preserves encounter order |
⚡ Performance | ✅ Faster in parallel | ⚠️ Slower in parallel (due to ordering) |
📦 Use case | When order doesn’t matter | When you need elements in original order |
✅ When to Use Which?
Situation | Method |
---|---|
Printing logs or performing side effects | forEach() |
Processing sequentially where order matters | forEachOrdered() |
Working with parallel streams and require order | forEachOrdered() |
Maximizing parallel speed (order doesn’t matter) | forEach() |
🧠 Bonus Tip
Both forEach()
and forEachOrdered()
are terminal operations — meaning:
- They trigger the execution of the stream
- Once you call them, the stream is consumed and cannot be reused
✅ Summary
- Use
**forEach()**
for speed when order doesn’t matter - Use
**forEachOrdered()**
for consistency when order is important