Java 8 – Flatten Collections with FlatMap

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

  1. Input Collection: Start with a collection containing nested collections that can either be hardcoded or provided by the user.
  2. Flatten the Collection Using flatMap: Use the flatMap() method to flatten the nested collections into a single list.
  3. 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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top