Introduction
When working with nested collections, such as a list of lists, you may often need to flatten these collections into a single list. Java 8 introduced the flatMap
method in the Stream API, which allows you to achieve this in a clean and efficient manner. Flattening collections is particularly useful when processing hierarchical data structures or when you need to apply a single operation across all elements in a nested collection. In this guide, we’ll explore how to flatten collections using Java 8’s flatMap
method, covering various scenarios including lists of lists and custom objects.
Table of Contents
- Problem Statement
- Solution Steps
- Java Program
- Flattening a List of Lists
- Flattening a List of Arrays
- Flattening a List of Custom Objects with Nested Collections
- Advanced Considerations
- Conclusion
Problem Statement
The task is to create a Java program that:
- Accepts a collection containing nested collections.
- Flattens the nested collections into a single list.
- Outputs the flattened list.
Example 1:
- Input: List of lists
[[1, 2], [3, 4], [5, 6]]
- Output: List
[1, 2, 3, 4, 5, 6]
Example 2:
- Input: List of custom
Student
objects, where each student has a list of courses. - Output: A single list of all courses.
Solution Steps
- Input Collection: Start with a collection containing nested collections that can either be hardcoded or provided by the user.
- Flatten the Collection Using
flatMap
: Use theflatMap()
method to flatten the nested collections into a single list. - Display the Result: Print the flattened list.
Java Program
Flattening a List of Lists
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Java 8 - Flatten a List of Lists Using flatMap
* Author: https://www.rameshfadatare.com/
*/
public class FlattenListOfLists {
public static void main(String[] args) {
// Step 1: Take input list of lists
List<List<Integer>> listOfLists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)
);
// Step 2: Flatten the list of lists into a single list
List<Integer> flattenedList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// Step 3: Display the result
System.out.println("Flattened list: " + flattenedList);
}
}
Output
Flattened list: [1, 2, 3, 4, 5, 6]
Explanation
- The
stream()
method is used to create a stream from the list of lists. - The
flatMap(List::stream)
method flattens the nested lists into a single stream of elements. - The
collect(Collectors.toList())
method collects the elements into a new list. - The resulting list
[1, 2, 3, 4, 5, 6]
is printed to the console.
Flattening a List of Arrays
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Java 8 - Flatten a List of Arrays Using flatMap
* Author: https://www.rameshfadatare.com/
*/
public class FlattenListOfArrays {
public static void main(String[] args) {
// Step 1: Take input list of arrays
List<String[]> listOfArrays = Arrays.asList(
new String[]{"apple", "banana"},
new String[]{"orange", "grape"},
new String[]{"pear", "kiwi"}
);
// Step 2: Flatten the list of arrays into a single list
List<String> flattenedList = listOfArrays.stream()
.flatMap(Arrays::stream)
.collect(Collectors.toList());
// Step 3: Display the result
System.out.println("Flattened list: " + flattenedList);
}
}
Output
Flattened list: [apple, banana, orange, grape, pear, kiwi]
Explanation
- The
stream()
method is used to create a stream from the list of arrays. - The
flatMap(Arrays::stream)
method flattens the nested arrays into a single stream of elements. - The
collect(Collectors.toList())
method collects the elements into a new list. - The resulting list
["apple", "banana", "orange", "grape", "pear", "kiwi"]
is printed to the console.
Flattening a List of Custom Objects with Nested Collections
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Java 8 - Flatten a List of Custom Objects with Nested Collections Using flatMap
* Author: https://www.rameshfadatare.com/
*/
public class FlattenCustomObjectCollections {
public static void main(String[] args) {
// Step 1: Take input list of custom objects
List<Student> students = Arrays.asList(
new Student("Raj", Arrays.asList("Math", "Physics")),
new Student("Anita", Arrays.asList("Chemistry", "Biology")),
new Student("Vikram", Arrays.asList("History", "Geography"))
);
// Step 2: Flatten the list of courses into a single list
List<String> allCourses = students.stream()
.flatMap(student -> student.getCourses().stream())
.collect(Collectors.toList());
// Step 3: Display the result
System.out.println("All courses: " + allCourses);
}
}
// Custom class Student
class Student {
private String name;
private List<String> courses;
public Student(String name, List<String> courses) {
this.name = name;
this.courses = courses;
}
public String getName() {
return name;
}
public List<String> getCourses() {
return courses;
}
}
Output
All courses: [Math, Physics, Chemistry, Biology, History, Geography]
Explanation
- The list of
Student
objects is processed to flatten the nested list of courses. - The
flatMap(student -> student.getCourses().stream())
method flattens the nested collections into a single stream of courses. - The
collect(Collectors.toList())
method collects the elements into a new list. - The resulting list
["Math", "Physics", "Chemistry", "Biology", "History", "Geography"]
is printed to the console.
Advanced Considerations
- Null Handling: If there’s a possibility of
null
values in the nested collections, you should filter them out before flattening:List<String> allCourses = students.stream() .flatMap(student -> student.getCourses() != null ? student.getCourses().stream() : Stream.empty()) .collect(Collectors.toList());
- Performance Considerations: Flattening very large nested collections can be resource-intensive. Consider the size of the collections and the depth of nesting when using
flatMap
. - Combining Flattening with Other Operations: You can combine
flatMap
with other stream operations, such as filtering, mapping, or sorting, to perform more complex data transformations:List<String> sortedCourses = students.stream() .flatMap(student -> student.getCourses().stream()) .sorted() .collect(Collectors.toList());
Conclusion
This guide provides methods for flattening collections using Java 8’s flatMap
method, covering various scenarios, including lists of lists, arrays, and custom objects with nested collections. The flatMap
method offers a powerful and concise way to transform and flatten complex data structures, making your code more readable and maintainable. Depending on your specific use case, you can easily apply the techniques demonstrated in this guide to flatten nested collections and simplify your data processing tasks.