Understanding Java Stream: How Lazy Pipelines Transform Collections
This article explains the core principles of Java Stream, covering its three main characteristics, pipeline construction, intermediate and terminal operations with code examples, and how lazy execution and sink generation produce results only when a terminal operation is invoked.
Overview
This article briefly explains the principle of Java Stream and uses a simple, common stream operation code example to illustrate how streams replace traditional loops with a fluent, pipeline‑style approach.
Three Key Characteristics of Streams
1. Streams do not store elements ; the elements may reside in the underlying collection or be generated on demand.
2. Stream operations do not modify the original data elements; they produce a new stream.
3. Stream operations are executed lazily , meaning they run only when the result is needed.
Stream Execution Flow
A Stream execution consists of three parts: building the pipeline, reverse‑indexing to create operation instances (Sinks), and feeding the data source through the pipeline to generate the final result.
Building the Pipeline
Define Input Source (HEAD)
Only classes that implement the Collection interface can create a stream; Map cannot. Lists and Sets can use stream(), Stream.of(), or Arrays.stream() to create a source.
List<String> startlist = Lists.newArrayList("a","b","c"); List<String> endList = startlist.stream().map(r->r+"b").filter(r->r.startsWith("a")).collect(Collectors.toList());Intermediate Operations
map()
Maps each element by appending "b".
Stream<String> mapStream = startlist.stream().map(r->r+"b");filter()
Filters elements that start with "a".
Stream<String> filterStream = startlist.stream().map(r->r+"b").filter(r->r.startsWith("a"));Terminal Operation
collect()
Collects the stream into a List, producing the final result ["ab"].
List<String> endList = startlist.stream().map(r->r+"b").filter(r->r.startsWith("a")).collect(Collectors.toList());Reverse Indexing and Sink Generation
When a terminal operation is invoked, the framework walks the pipeline backwards, wrapping each intermediate operation into a Sink object. This creates a chain of sinks where each sink delegates to the previous one, ultimately linking the source Spliterator to the terminal sink.
The reverse‑indexing process results in a nested sink structure that mirrors the pipeline stages (Head → map → filter → collect).
Launching the Pipeline
After the sink chain is built, copyInto pushes the data source through the pipeline. The begin method of each sink is called, followed by repeated accept calls for each element, executing the lambda logic defined in map and filter. Finally, end finalizes the processing.
Summary
The Stream API builds a pipeline using a doubly linked list of nodes; each node creates a new Stream object, preserving the original collection. Because operations are lazy, no data is produced until a terminal operation triggers execution, at which point the sink chain processes the source elements and yields the final result.
References
1. "Java Core Technology, Volume II"
2. Original article: https://zhuanlan.zhihu.com/p/47478339
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
