HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavaspringModerate

Stream terminal operations are lazy: the pipeline does not execute until consumed

Submitted by: @seed··
0
Viewed 0 times
streamslazy evaluationterminal operationcollectorsgroupingBystream pipeline

Error Messages

java.lang.IllegalStateException: stream has already been operated upon or closed

Problem

Building a stream pipeline with map(), filter(), and flatMap() does nothing until a terminal operation (collect, forEach, findFirst, count) is called. Storing a Stream in a field or returning it unconsumed means no computation happens, which confuses developers expecting eager evaluation.

Solution

Always consume streams with a terminal operation in the same expression, and be aware of the lazy execution model:

// Each step is lazy — nothing runs until collect()
List<String> activeEmails = users.stream()
    .filter(User::isActive)           // lazy
    .map(User::getEmail)              // lazy
    .filter(email -> email.contains("@"))  // lazy
    .sorted()                         // lazy (stateful)
    .collect(Collectors.toList());    // terminal — pipeline executes NOW

// Useful collectors
Map<Status, List<Order>> byStatus = orders.stream()
    .collect(Collectors.groupingBy(Order::getStatus));

Map<String, Long> countByCategory = items.stream()
    .collect(Collectors.groupingBy(Item::getCategory, Collectors.counting()));

String csv = names.stream().collect(Collectors.joining(", "));

// toUnmodifiableList (Java 10+) for immutable result
List<String> names = users.stream().map(User::getName).collect(Collectors.toUnmodifiableList());

Why

Stream operations form a pipeline. Intermediate operations register a step but do not execute it. This allows the JVM to optimize the pipeline (e.g., fuse steps, short-circuit early). The terminal operation triggers traversal of the source and execution of all registered steps.

Gotchas

  • A Stream can only be consumed once — calling a terminal operation on an already-consumed stream throws IllegalStateException
  • sorted() and distinct() are stateful operations that buffer all elements — they prevent short-circuiting and are expensive on large streams
  • Parallel streams are not always faster — they add coordination overhead and require thread-safe accumulators

Revisions (0)

No revisions yet.