map vs flatMap
TL;DR
map()transforms one object into another object. (One-to-One).flatMap()transforms one object into a Stream of objects, and then “flattens” all those streams into a single massive stream. (One-to-Many).
Concept
The map operation
Use map when every element in your stream corresponds to exactly one output element.
If you have a Stream<String> and you map each string to its length, you get a Stream<Integer>.
The flatMap operation
Use flatMap when you have a stream of complex objects (like Lists), and you want to extract all the items inside those lists into a single, flat stream.
If you have a Stream<List<String>> (a stream of lists), and you use map, you just get a transformed Stream<List<String>>. But if you use flatMap, it extracts the Strings from every inner list and merges them, resulting in a single Stream<String>.
Examples
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MapVsFlatMap {
public static void main(String[] args) {
// --- 1. map() Example ---
List<String> words = Arrays.asList("hello", "world");
List<Integer> lengths = words.stream()
.map(String::length) // 1 word -> 1 length
.collect(Collectors.toList());
System.out.println(lengths); // [5, 5]
// --- 2. flatMap() Example ---
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d"),
Arrays.asList("e", "f")
);
// If we used map(List::stream), we would get Stream<Stream<String>>
// flatMap merges them all into a single Stream<String>
List<String> flatList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(flatList); // [a, b, c, d, e, f]
}
}
Interview Questions
Q: When should you use flatMap with Optional?
A: In Java 8, Optional acts somewhat like a stream of 0 or 1 elements. If you have an Optional<User> and you call map(User::getAddress), you get an Optional<Address>. But what if getAddress() itself returns an Optional<Address>? Using map would result in a nested Optional<Optional<Address>>. In this scenario, you use flatMap(User::getAddress) to flatten it into a single Optional<Address>.
Q: Does flatMap improve performance?
A: Not inherently. flatMap is a structural operation used to change the shape of your data (from nested collections to a flat sequence). It does extra work to manage and merge multiple streams. You use it because the logic dictates it, not to optimize performance.