Feature / Use Case
β
.map()
β
.flatMap()
Purpose
β
Transforms each element into exactly one new element
β
Transforms each element into zero, one, or many elements, then flattens into a single stream
Return type of mapper
β
Function<T, R> β returns a single value
β
Function<T, Stream<R>> β returns a stream for each element
Output Stream
β
Stream of transformed elements
β
Stream of flattened elements
When to use
β
One-to-one mapping (e.g., String β Integer)
β
One-to-many mapping (e.g., String β List<String>)
Example Input
β
["apple", "banana"]
β
["apple banana", "cherry date"]
Example Output
β
[5, 6] (lengths)
β
["apple", "banana", "cherry", "date"] (split words)
Example 1 β .map() (One-to-One)
import java.util.*;
import java.util.stream.*;
public class MapVsFlatMap1 {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana");
List<Integer> lengths = words.stream()
.map(String::length) // String β Integer
.collect(Collectors.toList());
System.out.println(lengths); // [5, 6]
}
}
Example 2 β .flatMap() (One-to-Many)
import java.util.*;
import java.util.stream.*;
public class MapVsFlatMap2 {
public static void main(String[] args) {
List<String> phrases = Arrays.asList("apple banana", "cherry date");
List<String> allWords = phrases.stream()
.flatMap(p -> Arrays.stream(p.split(" "))) // String β Stream<String>
.collect(Collectors.toList());
System.out.println(allWords); // [apple, banana, cherry, date]
}
}
- Quick Rule of Thumb
.map()β You end up with Stream<R> .flatMap()β You end up with Stream<R> but flattened from multiple sub-streams
π‘ Pro Tips:
If your mapping function returns a collection, array, or another stream, you almost always need.flatMap()to avoid nested structures likeStream<List<T>>.
If you want, I can also make a visual diagram showing how.map()and.flatMap()transform data step-by-step β thatβs often the easiest way to remember the difference.