map() and flatMap() are both Stream transformation operations, but map() converts each element one-to-one into a new value, while flatMap() converts each element into a stream and then flattens all those streams into a single, combined stream.
Key Points: • map(Function<T,R>) returns a Stream<R> where each input element becomes exactly one output element. • flatMap(Function<T, Stream<R>>) requires the mapping function to return a Stream, which flatMap then merges into one flat stream. • flatMap() is the tool of choice for flattening nested structures, like a List<List<Integer>> or a stream of word lists. • Using map() on a nested collection produces a stream of streams (e.g. Stream<List<String>>), which usually isn't what you want — flatMap() avoids that extra nesting. • Both are intermediate, lazy operations that can be followed by further pipeline steps.
Example: Given a List<List<String>> of sentences split into words, lists.stream().flatMap(List::stream) produces a single Stream<String> of all words, whereas lists.stream().map(List::size) would just produce a stream of list sizes.
Code Example:
List<List<Integer>> nested = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5),
Arrays.asList(6)
);
List<Integer> flat = nested.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(flat); // [1, 2, 3, 4, 5, 6]Interview Tip: A concise interview answer is:
"map() transforms each element into exactly one new element, so a stream of N elements stays a stream of N elements. flatMap() expects the mapping function to return a stream per element and then flattens all of those into a single stream, which is what you need when you're dealing with nested collections and want one combined stream of the inner elements."