flatMap
TL;DR
flatMap()is an intermediate operation used to flatten complex, nested data structures into a single flat stream.- It applies a function that returns a
Streamfor each element, and then merges all those returned streams into one single stream. - Used for One-to-Many transformations.
Concept
If you have a List<Student>, and each Student has a List<String> subjects, how do you get a list of all subjects taught at the school?
If you use .map(Student::getSubjects), you will get a Stream<List<String>>.
flatMap() solves this. It takes each student, gets their list of subjects, turns that list into a Stream, and then flattens all those individual streams into one continuous Stream<String>.
Examples
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class Student {
private String name;
private List<String> subjects;
public Student(String name, List<String> subjects) {
this.name = name;
this.subjects = subjects;
}
public List<String> getSubjects() { return subjects; }
}
public class FlatMapExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Alice", Arrays.asList("Math", "Physics")),
new Student("Bob", Arrays.asList("History", "Math"))
);
// 1. Extract and flatten all subjects
List<String> allSubjects = students.stream()
// Student -> Stream<String>
.flatMap(student -> student.getSubjects().stream())
.distinct() // Remove duplicates (like Math)
.collect(Collectors.toList());
System.out.println(allSubjects); // [Math, Physics, History]
}
}
Interview Questions
Q: What happens if the function passed to flatMap returns null?
A: If the function passed to flatMap returns null instead of a Stream, it will throw a NullPointerException. The function must return a Stream (it can return an empty stream via Stream.empty(), but it cannot be null).
Q: When should you use flatMap instead of map?
A: Use map when you want a 1-to-1 transformation (e.g., transforming a String to an Integer). Use flatMap when the transformation results in multiple elements (a Collection or a Stream) that you want to merge into the main stream pipeline, preventing nested streams like Stream<Stream<T>>.