Skip to content

Lazy and Eager Processing

Eager processing performs work before the result is requested. Lazy processing defers work until consumption. Laziness can avoid unnecessary computation and support pipelines; eagerness can make cost, errors, snapshots, and resource ownership easier to reason about.

The three times to distinguish

For a lazy value, separate:

  1. construction of the recipe;
  2. traversal or evaluation;
  3. release of resources retained by the recipe.

Java Stream intermediate operations are lazy and a terminal operation begins traversal. A stream is single-use. If its source is mutable, results depend on the source state when traversal occurs, not necessarily when the pipeline was declared.

List<String> normalized = names.stream()
        .filter(Objects::nonNull)
        .map(String::strip)
        .filter(name -> !name.isEmpty())
        .toList();

toList() establishes an eager materialization boundary. That boundary can be valuable before leaving a transaction, closing a file, or handing data to another thread.

Persistence hazards

ORM lazy associations may issue a query when traversed. Access after the persistence context closes can fail; access inside a loop can create the N+1 query problem. Blanket eager fetching is not a solution: it can load unused graphs or multiply rows. Fetch exactly what a use case needs with a projection, explicit query, or carefully selected graph.

Concurrency and repeated work

Lazy initialization shared between threads needs safe publication and a stated failure policy. A thread-safe reference alone may still permit duplicate work. Also decide whether a failed initialization may be retried. A lazy sequence that recomputes on every traversal is different from memoization, which retains results.

Decision questions

  • Is the result likely to be unused or only partly consumed?
  • Must errors happen at a predictable boundary?
  • Does evaluation retain a file, connection, transaction, or large object graph?
  • Is a stable snapshot required?
  • Will repeated traversal repeat expensive or observable work?

Prefer explicit materialization at ownership and resource boundaries. Use laziness where deferred or partial evaluation has measurable value.