All topics
streams
intermediate

Stream Pipelines

Declarative pipelines for processing data — filter, map, reduce — that read like a description of what you want, not how to loop.

The Stream API, introduced in Java 8, lets you express data processing as a declarative pipeline rather than an imperative loop. Instead of writing out the iteration, the temporary collections, and the bookkeeping, you describe the sequence of transformations you want — filter these, map those, collect the rest — and the stream handles the mechanics. The result reads like the intent of the computation.

A factory assembly line — raw items in, each station transforms or rejects them, packaging at the end. Nothing moves until the packaging line pulls.

Key Concepts

1
A pipeline has three parts: a source (a collection, array, generator, or I/O channel), zero or more intermediate operations, and exactly one terminal operation. Intermediate operations like filter, map, sorted, and distinct are lazy — they return a new stream and do no work until a terminal operation like collect, forEach, reduce, or count is invoked. This laziness enables a crucial optimisation: the elements are pulled through the whole pipeline one at a time, and operations fuse so that, for example, findFirst after a filter stops as soon as it has its answer instead of filtering the entire source. Streams are also single-use — once a terminal operation runs, the stream is consumed and must be recreated to be traversed again.
filtermapsorteddistinctcollect
2
The mental shift is from "how to loop" to "what to compute," and it pays off in readability and composability, especially for chained transformations. The caveats worth knowing: streams are not always faster than a plain loop — for small collections or simple operations the abstraction overhead can make them slightly slower — so prefer them for clarity rather than as a blanket performance win. The lambdas you pass should be stateless and side-effect-free; mutating shared state from within a stream, or relying on the encounter order in an unordered or parallel stream, leads to subtle bugs. And a stream is not a data structure — it carries no storage and computes on demand.