1. The Hook (The "Byte-Sized" Intro)
- In a Nutshell: Intermediate operations (return Stream, lazy): filter() (keep matching), map() (transform 1β1), flatMap() (flatten nested, 1βmany), distinct() (remove duplicates), sorted() (order), limit()/skip() (pagination), peek() (debug).
- Terminal operations (trigger execution): forEach(), collect(), reduce(), count(), anyMatch/allMatch(), findFirst/findAny(), min/max().
- Chaining: Combine operations into pipelines.
- Short-circuiting: limit(), anyMatch() stop early!
Think of water filtration plant. filter() = remove impurities (keep clean water). map() = add fluoride (transform). flatMap() = merge multiple streams. sorted() = organize by quality. collect() = bottle water (final output). Each stage processes, terminal stage delivers!
2. Conceptual Clarity (The "Simple" Tier)
π‘ The Analogy: Food Processing
- filter(): Quality inspector (reject bad apples)
- map(): Slicer (whole apple β apple slices)
- flatMap(): Unboxer (box of bags β individual items)
- sorted(): Sorter (by size/color)
- collect(): Packaging (final product)
3. Technical Mastery (The "Deep Dive")
Operation Categories
| Operation | Type | Returns | Purpose |
|---|---|---|---|
| filter | Intermediate | Stream | Keep matching elements |
| map | Intermediate | Stream | Transform 1β1 |
| flatMap | Intermediate | Stream | Flatten, 1βmany |
| distinct | Intermediate | Stream | Remove duplicates |
| sorted | Intermediate | Stream | Order elements |
| peek | Intermediate | Stream | Side effects (debug) |
| limit/skip | Intermediate | Stream | Pagination |
| forEach | Terminal | void | Iterate |
| collect | Terminal | Collection | Gather results |
| reduce | Terminal | Optional/T | Combine to single value |
4. Interactive & Applied Code
java
import java.util.*;
import java.util.stream.*;
public class StreamOperationsDemo {
public static void main(String[] args) {
demonstrateFilter();
demonstrateMap();
demonstrateFlatMap();
demonstrateDistinct();
demonstrateSorted();
demonstrateCollect();
demonstrateReduce();
demonstrateMatching();
}
// filter(): Keep matching elements
static void demonstrateFilter() {
System.out.println("=== FILTER ===");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Filter even numbers
List<Integer> evens = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println("Evens: " + evens);
// Multiple filters (chained)
List<Integer> result = numbers.stream()
.filter(n -> n % 2 == 0) // Even
.filter(n -> n > 5) // > 5
.collect(Collectors.toList());
System.out.println("Even AND >5: " + result);
}
// map(): Transform 1β1
static void demonstrateMap() {
System.out.println("\n=== MAP ===");
List<String> words = Arrays.asList("apple", "banana", "cherry");
// Transform to uppercase
List<String> upper = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("Uppercase: " + upper);
// Transform to length
List<Integer> lengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println("Lengths: " + lengths);
// Chained transformations
List<Integer> result = words.stream()
.map(String::toUpperCase)
.map(String::length)
.map(n -> n * 2)
.collect(Collectors.toList());
System.out.println("Chain: " + result);
}
// flatMap(): Flatten nested structures
static void demonstrateFlatMap() {
System.out.println("\n=== FLATMAP ===");
List<List<Integer>> nested = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5),
Arrays.asList(6, 7, 8, 9)
);
// Flatten to single stream
List<Integer> flattened = nested.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println("Flattened: " + flattened);
// Split strings into characters
List<String> words = Arrays.asList("Hello", "World");
List<String> chars = words.stream()
.flatMap(s -> Arrays.stream(s.split("")))
.collect(Collectors.toList());
System.out.println("Characters: " + chars);
}
// distinct(): Remove duplicates
static void demonstrateDistinct() {
System.out.println("\n=== DISTINCT ===");
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4, 5, 5);
List<Integer> unique = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println("Unique: " + unique);
}
// sorted(): Order elements
static void demonstrateSorted() {
System.out.println("\n=== SORTED ===");
List<String> words = Arrays.asList("banana", "apple", "cherry", "date");
// Natural order
List<String> sorted1 = words.stream()
.sorted()
.collect(Collectors.toList());
System.out.println("Natural: " + sorted1);
// Custom comparator (by length)
List<String> sorted2 = words.stream()
.sorted(Comparator.comparingInt(String::length))
.collect(Collectors.toList());
System.out.println("By length: " + sorted2);
// Reverse order
List<String> sorted3 = words.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
System.out.println("Reverse: " + sorted3);
}
// collect(): Gather results
static void demonstrateCollect() {
System.out.println("\n=== COLLECT ===");
List<String> words = Arrays.asList("apple", "banana", "cherry");
// To List
List<String> list = words.stream().collect(Collectors.toList());
// To Set
Set<String> set = words.stream().collect(Collectors.toSet());
// To Map
Map<String, Integer> map = words.stream()
.collect(Collectors.toMap(
w -> w, // Key
String::length // Value
));
System.out.println("Map: " + map);
// Joining strings
String joined = words.stream()
.collect(Collectors.joining(", "));
System.out.println("Joined: " + joined);
// Partitioning (split into two groups)
Map<Boolean, List<String>> partitioned = words.stream()
.collect(Collectors.partitioningBy(w -> w.length() > 5));
System.out.println("Long words: " + partitioned.get(true));
System.out.println("Short words: " + partitioned.get(false));
// Grouping by length
Map<Integer, List<String>> grouped = words.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println("Grouped: " + grouped);
}
// reduce(): Combine to single value
static void demonstrateReduce() {
System.out.println("\n=== REDUCE ===");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Sum
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("Sum: " + sum);
// Product
int product = numbers.stream()
.reduce(1, (a, b) -> a * b);
System.out.println("Product: " + product);
// Max (returns Optional)
Optional<Integer> max = numbers.stream()
.reduce((a, b) -> a > b ? a : b);
max.ifPresent(m -> System.out.println("Max: " + m));
}
// anyMatch, allMatch, noneMatch
static void demonstrateMatching() {
System.out.println("\n=== MATCHING ===");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);
System.out.println("Has even: " + hasEven);
boolean allPositive = numbers.stream().allMatch(n -> n > 0);
System.out.println("All positive: " + allPositive);
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);
System.out.println("None negative: " + noneNegative);
// findFirst / findAny
Optional<Integer> first = numbers.stream()
.filter(n -> n > 3)
.findFirst();
first.ifPresent(f -> System.out.println("First >3: " + f));
}
}5. The Comparison & Decision Layer
| Task | Operation | Example |
|---|---|---|
| Remove items | filter() | s -> s.length() > 5 |
| Transform | map() | String::toUpperCase |
| Flatten | flatMap() | list -> list.stream() |
| Remove dups | distinct() | stream.distinct() |
| Order | sorted() | sorted(Comparator...) |
| Collect | collect() | Collectors.toList() |
| Combine | reduce() | (a,b) -> a + b |
6. The "Interview Corner" (The Edge)
The "Killer" Interview Question: "map() vs flatMap()?" Answer: map() = 1β1, flatMap() = 1βmany (flattens)!
java
List<String> words = Arrays.asList("Hello", "World");
// map(): Each word β Stream<String>
// Result: Stream<Stream<String>> (nested!)
words.stream()
.map(w -> Arrays.stream(w.split("")))
// Type: Stream<Stream<String>> β
// flatMap(): Flattens automatically
words.stream()
.flatMap(w -> Arrays.stream(w.split("")))
// Type: Stream<String> β
.forEach(System.out::println); // H e l l o W o r l dPro-Tip: limit() short-circuits (stops early):
java
// Processes only 5 elements (not all 1M!)
Stream.iterate(0, n -> n + 1) // Infinite!
.limit(5)
.forEach(System.out::println); // 0 1 2 3 4