Java Stream API & Collectors —
Complete Guide
Introduction
This document explains the Java Stream API and Collectors in detail. Each method is covered
with examples, corner cases, and explanations. Frequently used methods are highlighted.
Streams Overview
A Stream is a sequence of elements supporting aggregate operations. It consists of a pipeline
of: Source → Intermediate Operations → Terminal Operation.
// Example: Stream pipeline
List<String> result = words.stream()
.filter(w -> w.length() > 3)
.map(String::toUpperCase)
.sorted()
.toList();
Intermediate Operations
Stateless: filter, map, flatMap, peek, mapMulti
Stateful: distinct, sorted, limit, skip, takeWhile, dropWhile
// Flatten nested lists and remove duplicates
List<String> tags = posts.stream()
.flatMap(p -> p.getTags().stream())
.distinct()
.sorted()
.toList();
Terminal Operations
forEach, toArray, reduce, collect, min, max, count, anyMatch, allMatch, findFirst, findAny,
toList
// Reduce vs Collect
int sum = numbers.stream().reduce(0, Integer::sum);
int sum2 = numbers.stream().collect(Collectors.summingInt(x -> x));
Collectors
Collectors help transform stream elements into collections, maps, strings, or perform
aggregations.
toMap and groupingBy
// toMap with merge function
Map<String,Integer> scores = entries.stream()
.collect(Collectors.toMap(
e -> e.getName(),
e -> e.getScore(),
Integer::max
));
// groupingBy
Map<String, Long> deptCounts = emps.stream()
.collect(Collectors.groupingBy(
Emp::getDepartment,
Collectors.counting()
));
Corner Cases
• Empty min/max returns Optional — must handle.
• toMap throws IllegalStateException on duplicates unless merge function provided.
• peek doesn’t execute without a terminal op.
• Stream.toList() (Java 16+) returns unmodifiable list.