Functional Programming & Streams
Stream Operations
The intermediate vocabulary —
map, filter, flatMap, sorted, distinct, limit/skip, takeWhile/dropWhile — and the terminals: reduce, collect, find*, *Match, min/max, toList.maptransforms 1→1;flatMaptransforms 1→many and flattens;mapMulti(Java 16) is its imperative siblingtakeWhile/dropWhile(Java 9) cut ordered streams at a conditionanyMatch/allMatch/noneMatchandfindFirst/findAnyshort-circuitreducefolds with an associative operation;collectbuilds containerssorted,distinctare stateful — they buffer; keep them late and rare
// All distinct words across all lines:
List<String> words = lines.stream()
.flatMap(line -> Arrays.stream(line.split("\\s+"))) // Stream<String> per line → one stream
.map(String::toLowerCase)
.distinct()
.toList();
// Optional-valued lookups compose the same way:
List<Order> orders = ids.stream()
.map(repo::findOrder) // Stream<Optional<Order>>
.flatMap(Optional::stream) // keep only present values
.toList();int totalChars = words.stream().mapToInt(String::length).sum(); // specialized reduce
Optional<String> longest = words.stream()
.max(Comparator.comparingInt(String::length));
boolean anyEmpty = words.stream().anyMatch(String::isEmpty); // stops at first hit
// General fold — identity, accumulator (must be associative):
int sum = numbers.stream().reduce(0, Integer::sum);reduce's operation must be associative and stateless — that contract is what lets the same code run parallel unchanged (Parallel Streams). If your reduction builds a mutable container (a list, a map, a StringBuilder), that's not reduce, that's collect — the mutable-reduction terminal (Collectors).