Card 04/ 10
All 10 cards
WalkthroughDifficulty: Intermediate1 min
Watching a Pipeline Touch Three Elements Out of a Thousand
Laziness is easy to state and hard to believe, so here is a pipeline that reports what it does. A thousand elements, a filter, a map and a findFirst.
Optional<String> first = numbers.stream()
.peek(n -> System.out.println("testing " + n))
.filter(n -> n % 300 == 0)
.map(n -> "found " + n)
.findFirst();What the pipeline actually does, element by element
Step 1 of 5
findFirst asks for one element
The terminal operation drives everything. It does not ask the source for a thousand elements — it asks for one, and the whole chain above it runs for that one element before the second is ever fetched.
Element 1 goes through the whole chain
testing 1peek prints, filter rejects it, and map is never reached for this element. A rejected element stops where it was rejected.
Elements 2 to 299 do the same
Each one is fetched, printed and rejected in turn. Nothing accumulates: at no point is there a list of filtered elements waiting for map.
Element 300 passes the filter and reaches map
testing 300This is the only element map is ever called on. The transformation runs once, not three hundred times and not a thousand.
findFirst has what it needs and stops
Elements 301 to 1000 are never fetched and never printed. Three hundred peek calls, three hundred filter calls, one map call — for a source of a thousand.
The run to remember: the terminal operation pulls, one element at a time, through the whole chain. That is why findFirst, anyMatch and limit can stop early, and why putting filter before map does less work than the other way round.
- Java
- Java Streams
- Performance