In Java 8, the Stream
interface provides a powerful method called flatMap
that is used for transforming and flattening elements in a stream. The flatMap
method is especially useful when you have a stream of collections or other nested structures and you want to transform and flatten these nested structures into a single stream of elements.
Definition
The flatMap
method is defined as follows:
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
Here:
T
is the type of elements in the original stream.R
is the type of elements in the resulting stream.- The
mapper
function takes an element of typeT
and returns a stream of elements of typeR
.
How flatMap
Works
The flatMap
method applies the given mapper
function to each element of the stream, which produces a stream of new values. These streams are then flattened into a single stream of values.
Example Usage
Consider an example where we have a list of sentences, and we want to transform it into a stream of words:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FlatMapExample {
public static void main(String[] args) {
List<String> sentences = Arrays.asList("Hello world", "Java 8 stream", "FlatMap example");
// Using flatMap to transform and flatten the stream
List<String> words = sentences.stream()
.flatMap(sentence -> Arrays.stream(sentence.split(" ")))
.collect(Collectors.toList());
// Printing the list of words
words.forEach(System.out::println);
}
}
Explanation
-
List<String> sentences: A list of sentences.
-
stream(): Creates a stream from the list of sentences.
-
flatMap: Applies a function to each sentence that splits it into an array of words and returns a stream of those words. The individual streams of words are then flattened into a single stream.
-
collect(Collectors.toList()): Collects the flattened stream of words into a list.
Practical Use Cases
-
Nested Collections: When dealing with nested collections,
flatMap
can be used to flatten the structure for easier processing. For example, flattening a list of lists into a single list. -
File Processing: Reading lines from multiple files and processing them as a single stream of lines.
-
Database Results: When querying a database, each row might contain collections (like a list of phone numbers for a contact).
flatMap
can be used to create a single stream of phone numbers from all contacts.
Advanced Example
Let's consider a more complex example where we have a list of students, and each student has a list of courses they are enrolled in. We want to create a stream of all unique course names that students are enrolled in:
Explanation
-
Student class: A simple class representing a student with a name and a list of courses.
-
List<Student> students: A list of students with their respective courses.
-
flatMap: Each student's list of courses is transformed into a stream of courses, and all these streams are flattened into a single stream.
-
distinct(): Ensures that only unique course names are included in the final list.
-
collect(Collectors.toList()): Collects the stream of unique course names into a list.
The flatMap
method is a powerful tool in the Java Stream API that allows for more complex data transformations and processing by flattening nested structures into a single stream.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class Student {
private String name;
private List<String> courses;
public Student(String name, List<String> courses) {
this.name = name;
this.courses = courses;
}
public List<String> getCourses() {
return courses;
}
}
public class FlatMapAdvancedExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("John", Arrays.asList("Math", "Science")),
new Student("Jane", Arrays.asList("Math", "History")),
new Student("Jack", Arrays.asList("History", "Science"))
);
// Using flatMap to get a stream of all unique course names
List<String> courses = students.stream()
.flatMap(student -> student.getCourses().stream())
.distinct()
.collect(Collectors.toList());
// Printing the list of unique course names
courses.forEach(System.out::println);
}
}