Introduced in Java 24, the Gatherer API is a powerful way to define custom intermediate operations in a Stream pipeline — something you couldn’t do easily before.
It’s like a customizable version of map(), filter(), and flatMap(), but with more control and state awareness.
| Feature Traditional | Stream Ops (map, filter, findFirst) | Gatherer API |
|---|---|---|
| Custom intermediate ops | Limited | Fully customizable |
| Stateful processing | Limited | Supported |
| Parallelism support | Complex, error-prone | Built-in, optional combiner |
| Short-circuiting | Limited | Supported |
| Incremental/asynchronous | No | Yes |
| Code simplicity | Simple for basic ops, complex for custom | Simpler for complex custom ops |
| Transform infinite streams | Difficult | Supported |
- Core Components of a Gatherer: A Gatherer transforms a stream of type T into a stream of type R. It has four main parts:
- Initializer: Sets up any necessary state (such as a buffer or counter).
- Integrator: Processes each element, possibly using the state, and decides whether to emit something downstream.
- Combiner (optional): Merges states when processing in parallel.
- Finisher (optional): Emits final results when the stream ends (like flushing a buffer).
- Spliterator API V/s Gatherer API
- Spliterator API
- Supports parallelism but requires explicit splitting logic; can be tricky and error-prone.
- Used under the hood by Stream API; not designed for direct user customization of intermediate ops.
- Gatherer API
- Built-in excellent parallelism support; even sequential gatherers can run in parallel streams, benefiting from parallelism.
- Explicitly designed to be used with Stream.gather() for custom intermediate operations.
- Spliterator API