Skip to content
UniCircle
MediumConceptualModern Java

Streams: intermediate vs terminal operations

Question JAVA-MOD-030

How does the Stream API work? Explain lazy evaluation, intermediate vs terminal operations, and show a grouping example.

Show the explanation

A stream is a pipeline over a data source (a collection, an array, a file, a range). It does not store data and does not change the source.

  • Intermediate operations — filter, map, sorted, distinct, limit, flatMap — return a new stream and are lazy: nothing runs yet.
  • A terminal operation — collect, forEach, count, reduce, anyMatch, toList() — triggers the whole pipeline, element by element. A stream can be consumed only once.
Java
record Order(String city, int amount) {}
List<Order> orders = List.of(new Order("Pune", 300), new Order("Delhi", 120), new Order("Pune", 80));

int bigTotal = orders.stream()
        .filter(o -> o.amount() >= 100)
        .mapToInt(Order::amount)
        .sum();                                                   // 420

Map<String, Integer> byCity = orders.stream()
        .collect(Collectors.groupingBy(Order::city, TreeMap::new,
                 Collectors.summingInt(Order::amount)));          // {Delhi=120, Pune=380}

Because of laziness, limit and anyMatch can stop early (short-circuit). Keep lambdas free of side effects, and remember that parallelStream() only helps for large, CPU-heavy work — it is not a free speed-up.

Original UniCircle question. Last reviewed 22 Oct 2026.