Working with Stream API
1. Creating Streams
| Source | Method |
| Collection | coll.stream() / parallelStream() |
| Array | Arrays.stream(arr) / Stream.of(arr) |
| Values | Stream.of(a, b, c) |
| Empty | Stream.empty() |
| Infinite | Stream.iterate(seed, fn), Stream.generate(supplier) |
| Range | IntStream.range(0, n) |
| File lines | Files.lines(path) |
| Builder | Stream.<T>builder().add(...).build() |
| Operation | Description |
filter(p) | Keep matching |
map(fn) | Transform each |
flatMap(fn) | Map to stream, then flatten |
distinct() | Remove duplicates |
sorted() / sorted(cmp) | Sort elements |
limit(n) / skip(n) | Truncate |
peek(c) | Side-effect (debug) |
Note: Intermediate ops are LAZY — nothing happens until terminal op runs.
3. Using Terminal Operations
| Op | Returns |
forEach(c) | void |
toList() / toArray() | Collection |
collect(collector) | Custom result |
reduce(...) | Accumulated value |
count() | long |
min/max | Optional |
findFirst/findAny | Optional |
anyMatch/allMatch/noneMatch | boolean |
4. Filtering Elements
Example: Filter
List<User> active = users.stream()
.filter(User::isActive)
.filter(u -> u.age() >= 18)
.toList();
| Method | Detail |
filter(predicate) | Keep elements where predicate is true |
| Combine | Multiple filters chain naturally |
5. Mapping Elements
| Method | Use |
map(fn) | 1-to-1 transform |
mapToInt/Long/Double | Specialized streams (no boxing) |
mapToObj | From primitive back to object stream |
6. Flattening Streams
Example: flatMap
List<Order> orders = ...;
List<Item> allItems = orders.stream()
.flatMap(o -> o.items().stream())
.toList();
| Method | Use |
flatMap(fn) | 1-to-many → flat |
mapMulti(biCons) JAVA 16+ | Push-style flatMap (more efficient for few-to-one) |
7. Sorting Streams
| Form | Detail |
sorted() | Natural order (Comparable required) |
sorted(cmp) | Custom comparator |
| Stateful op | Buffers all elements |
8. Removing Duplicates
| Op | Detail |
distinct() | By equals/hashCode |
| Custom key | Use collectingAndThen(toMap(keyFn, identity(), (a,b)->a), m -> m.values().stream()) |
9. Limiting Streams
| Op | Detail |
limit(n) | First n elements (short-circuiting) |
skip(n) | Skip first n |
takeWhile(p) JAVA 9+ | Take while predicate true |
dropWhile(p) JAVA 9+ | Drop while predicate true |
10. Peeking Elements
| Aspect | Detail |
| Use | Debug logging mid-pipeline |
| Caution | Don't mutate state in peek |
11. Checking Conditions
| Method | Behavior |
anyMatch(p) | Short-circuit on first match |
allMatch(p) | Short-circuit on first non-match |
noneMatch(p) | Short-circuit on first match |
| Empty stream | allMatch=true, anyMatch=false, noneMatch=true |
12. Finding Elements
| Method | Behavior |
findFirst() | First per encounter order |
findAny() | Any element (better for parallel) |
| Returns | Optional<T> |
13. Understanding Parallel Streams
| Aspect | Detail |
| Activate | coll.parallelStream() or stream.parallel() |
| Backing | Common ForkJoinPool |
| Best for | Large data + CPU-bound + stateless ops |
| Avoid | I/O, shared mutable state, ordered ops |
Warning: Parallel streams use a shared pool — slow tasks can starve other parallel work.