Mastery
Mastery/Java/D. Streams & functional interfaces
T1 · high-leverage
Compare with Python: Lazy evaluation: nothing runs until you pull a value

Streams are lazy: nothing runs until a terminal operation

Intermediate operations (filter, map, peek, ...) just build up a pipeline description; none of them execute a single element until a terminal operation (findFirst, collect, forEach, ...) pulls values through. Terminal operations can also short-circuit, so a lazily-built pipeline may process far fewer elements than the source size. Watch the interleaving of print statements below — it proves the laziness, it doesn't just assert it.

java
import java.util.*;
import java.util.stream.*;

List<Integer> src = List.of(1, 2, 3, 4, 5);

var stream = src.stream()
        .peek(x -> System.out.println("  peek saw " + x))
        .filter(x -> x > 2);

System.out.println("stream pipeline built -- nothing printed above, because nothing has RUN yet");

Optional<Integer> first = stream.findFirst();   // terminal op, short-circuits after the first match
System.out.println("first element > 2: " + first + "  <- only elements 1..3 were ever peeked at, not all 5");

Interview angle

Frequently probed with a "will this line print anything?" question involving peek() or a filter before findFirst() — testing whether the candidate actually understands the pull-based execution model, versus having memorized "streams are lazy" as a fact they can't apply to predict real behavior.

In the industry

Misunderstanding stream laziness is a genuine source of production bugs: code that expects a stream's side effects to run eagerly (via peek or a mapped function with side effects), or that builds a stream once and tries to reuse it across two terminal operations — streams are single-use and throw IllegalStateException on a second terminal call. Both patterns show up regularly in code review feedback on teams newly adopting streams over classic for-loops.