Java Streams¶
A stream describes a pipeline over elements. It is not a collection and does not store its own elements. A pipeline contains a source, zero or more intermediate operations, and one terminal operation.
Laziness and single use¶
Intermediate operations such as map and filter are lazy; traversal begins
when a terminal operation requests results. A stream cannot be reused after a
terminal operation. The broader lazy-versus-eager guide
covers evaluation, resource lifetime, snapshots, and persistence hazards.
record Reading(String sensor, double value) {}
List<String> activeSensors = readings.stream()
.filter(reading -> reading.value() > 0.0)
.map(Reading::sensor)
.distinct()
.sorted()
.toList();
The source is not modified, but non-interference is a responsibility of the caller: mutating the source during traversal or mutating shared state from operations can make behavior unsafe or nondeterministic.
Operation categories¶
| Kind | Examples | Result |
|---|---|---|
| Stateless intermediate | map, filter |
Another stream |
| Stateful intermediate | distinct, sorted, limit |
Another stream, possibly buffered |
| Short-circuiting | findFirst, anyMatch, limit |
May stop early |
| Terminal reduction | reduce, collect, count |
Non-stream result |
peek is mainly an observation hook; do not make correctness depend on its side
effects because optimizations and short-circuiting affect which elements are
observed.
Reduction¶
Map<String, Double> maximumBySensor = readings.stream()
.collect(Collectors.toMap(
Reading::sensor,
Reading::value,
Math::max));
For parallel reduction, the identity and accumulator/combiner must satisfy the documented algebraic compatibility requirements. Associativity is essential; floating-point addition is not mathematically associative, so reassociation can change rounding.
Parallel streams¶
Parallelism is not a free speed switch. It works best for sufficiently large, CPU-bound, splittable workloads with stateless operations and cheap combining. Blocking I/O, shared mutation, encounter-order constraints, small inputs, and contention can make it slower or unsafe. Measure with a representative benchmark.
Exercises¶
- Replace a nested stream with
flatMap. - Explain the difference between
findFirstandfindAnyin parallel. - Write a collector that groups readings by sensor and computes summary statistics.