Comprehensive Java 8 Stream API Guide with 20 Practical Examples
This article provides a thorough introduction to Java 8's Stream and Lambda features, presenting twenty detailed code examples that cover stream creation, intermediate operations such as filter, map, flatMap, reduce, collect, and terminal operations including sorting, grouping, and parallel processing, helping developers master functional-style collection handling in Java.
This tutorial introduces Java 8's Stream API and the accompanying Lambda expressions, explaining how they simplify collection processing.
1. Stream Overview
Java 8 added Stream and Lambda, which treat a collection as a flow of elements that can be processed with operations like filtering, sorting, and aggregation.
Stream views the source elements as a pipeline; the Stream API provides intermediate and terminal operations for this pipeline.
Streams have two types of operations:
Intermediate operations – each returns a new stream and can be chained.
Terminal operations – each consumes the stream and produces a result (a collection, a value, or a side‑effect).
Key characteristics of streams:
Streams do not store data; they compute results on demand.
Streams do not modify the source; they usually produce a new collection or value.
Streams are lazily evaluated; intermediate operations run only when a terminal operation is invoked.
2. Stream Creation
Streams can be created from collections, arrays, or static factory methods.
From a collection:
List<String> list = Arrays.asList("a", "b", "c");
// sequential stream
Stream<String> stream = list.stream();
// parallel stream
Stream<String> parallelStream = list.parallelStream();From an array:
int[] array = {1,3,5,6,8};
IntStream stream = Arrays.stream(array);Using static methods:
Stream<Integer> s1 = Stream.of(1,2,3,4,5,6);
Stream<Integer> s2 = Stream.iterate(0, x -> x + 3).limit(4);
Stream<Double> s3 = Stream.generate(Math::random).limit(3);Parallel streams can be created directly or by calling parallel() on an existing stream.
Optional<Integer> findFirst = list.stream().parallel().filter(x -> x > 6).findFirst();3. Stream Usage
Before using streams, understand Optional, a container that may hold a null value.
3.1 Traversal / Matching
List<Integer> list = Arrays.asList(7,6,9,3,8,2,1);
list.stream().filter(x -> x > 6).forEach(System.out::println);
Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
boolean anyMatch = list.stream().anyMatch(x -> x < 6);
System.out.println("First match: " + findFirst.get());
System.out.println("Any match: " + findAny.get());
System.out.println("Contains >6: " + anyMatch);3.2 Filtering (filter)
Filters elements that satisfy a predicate and returns a new stream.
3.3 Aggregation (max/min/count)
Operations such as max, min, and count work similarly to SQL aggregate functions.
List<String> list = Arrays.asList("adnm","admmt","pot","xbangd","weoujgsd");
Optional<String> max = list.stream().max(Comparator.comparing(String::length));
System.out.println("Longest string: " + max.get());3.4 Mapping (map / flatMap)
maptransforms each element; flatMap flattens nested streams.
String[] strArr = {"abcd","bcdd","defde","fTr"};
List<String> upper = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());
List<Integer> plusThree = Arrays.asList(1,3,5,7,9,11).stream().map(x -> x + 3).collect(Collectors.toList());3.5 Reduction (reduce)
Reduces a stream to a single value.
List<Integer> list = Arrays.asList(1,3,2,8,11,4);
Optional<Integer> sum = list.stream().reduce((x,y) -> x + y);
Optional<Integer> product = list.stream().reduce((x,y) -> x * y);
Optional<Integer> max = list.stream().reduce((x,y) -> x > y ? x : y);3.6 Collecting (collect)
The collect operation gathers stream results into collections or other data structures using Collectors.
List<Integer> evens = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
Set<Integer> evenSet = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
Map<String, Person> map = personList.stream().filter(p -> p.getSalary() > 8000)
.collect(Collectors.toMap(Person::getName, p -> p));Statistical collectors such as counting, averagingDouble, summingInt, and summarizingDouble provide quick summaries.
3.7 Sorting (sorted)
Streams can be sorted naturally or with a custom comparator.
List<String> asc = personList.stream()
.sorted(Comparator.comparing(Person::getSalary))
.map(Person::getName)
.collect(Collectors.toList());
List<String> desc = personList.stream()
.sorted(Comparator.comparing(Person::getSalary).reversed())
.map(Person::getName)
.collect(Collectors.toList());3.8 Combining, Limiting, Skipping
Streams can be concatenated, made distinct, limited, or have elements skipped.
List<String> merged = Stream.concat(Stream.of(arr1), Stream.of(arr2)).distinct().collect(Collectors.toList());
List<Integer> limited = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
List<Integer> skipped = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());4. Stream Source Code Overview
The article mentions that a deeper source‑code analysis will be added later.
For the full original article, see the link below.
Original link: https://blog.csdn.net/mu_wind/article/details/109516995
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.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
