Master Java 8 Streams: From Basics to Powerful Operations

This article introduces Java 8 Stream API, explains its core concepts, shows how to generate streams, details intermediate and terminal operations with practical code examples, and provides a visual overview of the Stream hierarchy for developers seeking to write concise and efficient Java code.

Programmer DD
Programmer DD
Programmer DD
Master Java 8 Streams: From Basics to Powerful Operations

While reading Spring Boot source code, the extensive use of Java 8 features becomes evident, prompting a series of articles to help developers master these features.

private List<Profile> getOtherActiveProfiles(Set<Profile> activatedViaProperty) {
    return Arrays.stream(this.environment.getActiveProfiles())
        .map(Profile::new)
        .filter((profile) -> !activatedViaProperty.contains(profile))
        .collect(Collectors.toList());
}

The above snippet demonstrates how Java 8 streams can replace verbose loops with concise, fluent code.

What is Stream

In Java 8, a Stream ("流") is an abstract sequence of elements that supports declarative, parallelizable, and lazy operations similar to SQL queries, allowing developers to focus on "what" to compute rather than "how".

Stream concept diagram
Stream concept diagram

Stream Related Concepts

Element: an object of a specific type stored in a collection; streams do not store elements, they compute them on demand.

Data source: the origin of the stream, such as collections, arrays, I/O channels, or generators.

Aggregation operation: operations like filter, sorted, map that resemble SQL clauses.

Pipelining: intermediate operations return the stream itself, enabling fluent chaining and optimizations like laziness and short‑circuiting.

Internal iteration: streams use the Visitor pattern for internal iteration, unlike external iteration with Iterator or enhanced for‑loops.

Aggregation operations are evaluated lazily; they are only executed when a terminal operation (e.g., forEach) triggers the pipeline.

Stream Operation Method Classification

Intermediate operations: map, filter, distinct, sorted, peek, skip, parallel, sequential, unordered, etc.

Terminal operations: forEach, forEachOrdered, toArray, reduce, collect, min, max, count, iterator, etc.

Generating Streams

of creates a finite stream from given values.

Stream<String> stringStream = Stream.of("公众号");
Stream<String> stringsStream = Stream.of("关注", "公众号", "程序新视界");

generate creates an infinite stream using a Supplier.

Stream<Double> generateDouble = Stream.generate(Math::random);
Stream<String> generateString = Stream.generate(() -> "公众号:程序新视界");

iterate produces an infinite ordered stream by repeatedly applying a function.

Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println);

empty returns an empty stream.

Collection and Array Stream Methods

// Collection
default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); }
default Stream<E> parallelStream() { return StreamSupport.stream(spliterator(), true); }
// Arrays
static <T> Stream<T> stream(T[] array) { return stream(array, 0, array.length); }
static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) { return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false); }

Example usage:

List<String> list = new ArrayList<>();
list.add("欢迎关注");
list.add("微信公众号");
list.add("程序新视界");
list.stream().forEach(System.out::println);
int[] nums = new int[]{1,2,3,4,5};
Arrays.stream(nums).forEach(System.out::println);

Common Stream Operations

concat merges two streams.

Stream.concat(Stream.of("欢迎","关注"), Stream.of("程序新视界")).forEach(System.out::println);

distinct removes duplicate elements.

Stream.of(1,1,1).distinct().forEach(System.out::println);

filter selects elements that match a predicate.

Stream.of(1,2,3,4,5).filter(i -> i >= 3).forEach(System.out::println);

map transforms each element.

Stream.of("a","b","c").map(String::toUpperCase).forEach(System.out::println);

flatMap flattens nested streams.

Stream.of(1,2,3).flatMap(i -> Stream.of(i * 10)).forEach(System.out::println);

peek performs an action on each element without modifying the stream.

Stream.of(1,2).peek(i -> System.out.println("peekCall:" + i)).forEach(System.out::println);

skip discards the first N elements.

Stream.of(1,2,3).skip(2).forEach(System.out::println);

sorted sorts the elements.

Stream.of(1,3,2).sorted().forEach(System.out::println);

limit restricts the stream to the first N elements.

Stream.of(1,2,3).limit(2).forEach(System.out::println);

collect gathers the stream into a collection or other result.

Stream.of(1,2,3).collect(Collectors.toList());
Stream.of(1,2,3).collect(Collectors.toSet());

count returns the number of elements. long cnt = Stream.of(1,2,3).count(); forEach / forEachOrdered iterates over elements, optionally preserving encounter order. Stream.of(1,2,3).forEach(System.out::println); max / min find the greatest or smallest element.

Optional<Integer> max = Stream.of(1,2,3).max(Comparator.comparingInt(i -> i));
System.out.println("max:" + max.get());
Optional<Integer> min = Stream.of(1,2,3).min(Comparator.comparingInt(i -> i));
System.out.println("min:" + min.get());

reduce combines elements to produce a single value.

Integer sum = Stream.of(1,2,3).reduce(Integer::sum).get();
Integer sum2 = Stream.of(1,2,3).reduce(0, (a,b) -> a + b);
System.out.println(sum2);

allMatch / anyMatch / noneMatch test predicates across the stream.

boolean all = Stream.of(1,2,3).allMatch(i -> i > 0);
boolean any = Stream.of(1,2,3).anyMatch(i -> i > 2);
boolean none = Stream.of(1,2,3).noneMatch(i -> i > 5);
System.out.println(all);
System.out.println(any);
System.out.println(none);

findAny / findFirst retrieve an arbitrary or the first element.

Optional<String> any = Stream.of("A","B","C").findAny();
System.out.println(any.get());
Optional<String> first = Stream.of("A","B","C").findFirst();
System.out.println(first.get());

summaryStatistics provides statistical data for numeric streams.

IntSummaryStatistics stats = Stream.of(1,2,3).mapToInt(i -> i).summaryStatistics();
System.out.println("max:" + stats.getMax());
System.out.println("min:" + stats.getMin());
System.out.println("sum:" + stats.getSum());
System.out.println("average:" + stats.getAverage());

Bird's‑Eye View of Stream

Stream interface hierarchy
Stream interface hierarchy

The diagram shows BaseStream as the root, with Stream defining common operations, and specialized streams like IntStream, LongStream, and DoubleStream extending it. AbstractPipeline underpins the pipeline mechanism.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaLambdaStream APIJava 8
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.