Unravel โบ Java concepts โบ Collections and streams
Streams
A stream is a pipeline over a sequence of values: start from a source, chain steps such as filter and map, and finish with a terminal step such as collect.
Learn these first
At a glance
An assembly line.
- 1Source: list.stream(), Arrays.stream(a), IntStream.range(0, n)Intermediate steps (filter, map, sorted, distinct, limit, flatMap) each return a new stream and do no work yet.
- 2A terminal step (collect, toList, forEach, count, reduce, anyMatch, findFirst) starts the pipeline and produces the result
- 3Elements flow through all steps one at a time (not step by step over the whole list), which lets findFirst or limit stop early
- 4A stream can be used onceA second terminal operation throws IllegalStateException.
- Streams do not change the source collection; they build a new result
- A parallel stream uses the shared common fork-join pool
- A pipeline is a linked chain of stages
List<String> shouted = names.stream() .filter(n -> !n.isBlank()) .map(String::toUpperCase) .toList();- line 1 uses stream, the core of Streams
Read the full explanation (about 2 min)
A stream is a pipeline over a sequence of values: start from a source, chain steps such as filter and map, and finish with a terminal step such as collect. Nothing runs until the terminal step.
A mental model
An assembly line. Items pass through stations (filter out the bad ones, repaint, pack) one after another, and the line only starts moving when someone orders the finished boxes.
How it works
Source: list.stream(), Arrays.stream(a), IntStream.range(0, n). Intermediate steps (filter, map, sorted, distinct, limit, flatMap) each return a new stream and do no work yet.
A terminal step (collect, toList, forEach, count, reduce, anyMatch, findFirst) starts the pipeline and produces the result.
Elements flow through all steps one at a time (not step by step over the whole list), which lets findFirst or limit stop early.
A stream can be used once. A second terminal operation throws IllegalStateException.
Going deeper
Streams do not change the source collection; they build a new result. Keep lambdas free of side effects, especially with parallelStream(), where the order and threading are not yours to control.
A parallel stream uses the shared common fork-join pool. A blocking call inside it can slow unrelated parts of the application. It helps only for CPU-heavy work on big data; for small lists it is slower.
Collectors turn the result into the shape you want: toList, toSet, groupingBy (a Map of lists), counting, joining. Collectors.toMap throws on duplicate keys unless you give a merge function.
Readability beats cleverness: if a pipeline needs five nested lambdas, a simple loop is easier to debug.
Under the hood
A pipeline is a linked chain of stages. When the terminal step runs, a Spliterator produces elements and each stage wraps a Sink that passes the element to the next. This fuses all steps into a single pass without intermediate collections.
Common mistakes
- Expecting the stream to run without a terminal operation.
- Reusing a stream.
- Side effects and shared mutable state in lambdas.
- Using
parallelStream()by default. toMapwith duplicate keys.
How Unravel recognises it
When you paste code, Unravel looks for these signs of streams. Spotting them yourself is a good habit when you read unfamiliar code:
- Types:
StreamIntStreamCollectorsLongStream - Method calls:
stream()parallelStream()flatMap()collect()
Part of a learning path
- Modern Java: lambdas and streams ยท previous: Collections: List, Set, Map ยท next: Optional and null safety
Related concepts
Builds on this
Frequently asked questions
What is Streams?
A stream is a pipeline over a sequence of values: start from a source, chain steps such as filter and map, and finish with a terminal step such as collect. Nothing runs until the terminal step.
What are the most common mistakes with Streams?
Expecting the stream to run without a terminal operation. Reusing a stream. Side effects and shared mutable state in lambdas. Using parallelStream() by default. toMap with duplicate keys.
How can I see Streams in real code?
Paste your own Java into Unravel and it will point out where streams appears, explain how it works at the detail level you choose, and draw the flow of the code around it.