Medium java java-21

How does the Stream API work internally?

The 30 second answer

A stream is a pipeline: a source, some intermediate steps like filter and map, and one terminal step like collect. The intermediate steps only describe the work. When the terminal step runs, each element flows through all the steps one at a time, not stage by stage. A stream can be used once, and parallel streams split the source and run on the common fork-join pool.

A stream pipeline has three parts:

  1. Source: a collection, array, generator or I/O channel.
  2. Intermediate operations (filter, map, sorted): they return a new stream and are lazy.
  3. Terminal operation (collect, forEach, reduce, findFirst): it triggers processing and consumes the stream.
List<String> names = users.stream()     // source
    .filter(User::active)               // intermediate
    .map(User::name)                    // intermediate
    .toList();                          // terminal

Stateless operations like filter and map are fused, so each element passes through the whole chain before the next one starts. Stateful operations such as sorted or distinct may need to see all elements first. After a terminal operation the stream is consumed; reusing it throws IllegalStateException.

For parallel streams the source is split with a Spliterator, and the chunks run on ForkJoinPool.commonPool(). The docs require behavioral parameters to be non-interfering (don't modify the source during the pipeline) and preferably stateless; otherwise results can be wrong or nondeterministic.

Sources: java.util.stream package summary: stream operations and pipelines, Spliterator Javadoc

Sources (0)
See inline citations in the answer above.