Java Streams: Intermediate Operations
Intermediate operations transform, filter, or otherwise process elements in a Java Stream pipeline. They are lazy: their computation normally does not begin until a terminal operation is invoked.
Intermediate operations return another `Stream`, allowing multiple operations to be chained into a pipeline. Common examples include `filter`, `map`, `sorted`, `distinct`, `limit`, and `skip`.
These operations are lazy, meaning calling an intermediate method builds the pipeline rather than immediately processing the elements. The source is traversed when a terminal operation such as `collect`, `forEach`, `count`, or `findFirst` is executed.
Intermediate operations can be stateless or stateful. Operations such as `filter` and `map` can generally process elements independently, while operations such as `sorted` and `distinct` may need information about multiple elements before producing their results.
A stream pipeline can contain several intermediate operations before one terminal operation. Because streams are lazy and can often fuse processing steps, elements may pass through several stages during a single traversal rather than requiring a separate pass for every intermediate operation.
Key points
- Intermediate operations return a `Stream` and can be chained.
- They are lazy and normally execute only when a terminal operation runs.
- Examples include `filter`, `map`, `sorted`, `distinct`, `limit`, and `skip`.
- `filter` selects elements, while `map` transforms each element.
- Some intermediate operations, such as `sorted`, require more state than operations such as `map`.
Interview questions
What is the difference between `map` and `filter`?
`map` transforms each element into another value and therefore can change the element type. `filter` uses a predicate to decide whether each element remains in the stream. For example, `map(String::length)` converts strings to integers, while `filter(s -> s.length() > 3)` keeps only sufficiently long strings. Both are intermediate operations.
Why are intermediate operations called lazy?
They are lazy because invoking an intermediate operation generally only constructs another stage of the stream pipeline. The source is not normally traversed at that point. A terminal operation such as `collect` or `count` causes the pipeline to execute. This allows the stream implementation to organize processing across the pipeline.
What is an intermediate operation in the Java Streams API?
An intermediate operation is an operation that processes a stream and returns another stream. Examples include `filter`, `map`, `distinct`, and `sorted`. Intermediate operations are lazy, so calling one normally does not process the source immediately. Processing starts when a terminal operation is invoked.
Are all intermediate operations stateless?
No. Some intermediate operations are stateful. `map` and `filter` are typical stateless operations because processing one element does not generally require retaining information about other elements. Operations such as `sorted` and `distinct` may need information from multiple elements, so they are stateful and can have different performance characteristics.