Java 8 – Use FlatMap to Flatten Streams

Introduction

In Java 8, the Stream API introduced various methods to manipulate and process collections of data in a functional and declarative manner. One of the most versatile methods in the Stream API is flatMap(). This method is particularly useful when dealing with nested structures, such as lists of lists, and you need to flatten these structures into a single stream. The flatMap() method helps you transform and flatten complex data structures, making it easier to work with them in a streamlined way.

In this guide, we will explore how to use flatMap() to flatten streams. We’ll look at scenarios where you have nested lists, arrays, or collections and how to convert them into a single stream of elements.

Table of Contents

  • Problem Statement
  • Solution Steps
  • Java Program
    • Flattening a Stream of Lists
    • Flattening a Stream of Arrays
    • Flattening a Stream of Custom Objects
  • Advanced Considerations
  • Conclusion

Problem Statement

The task is to create a Java program that:

  • Accepts a nested structure (such as a list of lists or an array of arrays).
  • Uses the flatMap() method to flatten the structure into a single stream.
  • Outputs the flattened stream of elements.

Example 1:

  • Input: List of lists [[1, 2, 3], [4, 5], [6, 7, 8]]
  • Output: Flattened stream [1, 2, 3, 4, 5, 6, 7, 8]

Example 2:

  • Input: Array of arrays {{"apple", "banana"}, {"cherry", "date"}}
  • Output: Flattened stream ["apple", "banana", "cherry", "date"]

Solution Steps

  1. Create a Nested Structure: Start with a nested structure such as a list of lists or an array of arrays.
  2. Flatten the Structure Using flatMap(): Use the flatMap() method to transform and flatten the nested structure into a single stream.
  3. Display the Result: Print the flattened stream or collect it into a list.

Java Program

Flattening a Stream of Lists

One common use case for flatMap() is flattening a list of lists into a single list.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Java 8 - Flattening a Stream of Lists Using flatMap()
 * Author: https://www.rameshfadatare.com/
 */
public class FlattenStreamOfLists {

    public static void main(String[] args) {
        // Step 1: Create a list of lists
        List<List<Integer>> listOfLists = Arrays.asList(
            Arrays.asList(1, 2, 3),
            Arrays.asList(4, 5),
            Arrays.asList(6, 7, 8)
        );

        // Step 2: Flatten the list of lists using flatMap()
        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, 7, 8]

Explanation

  • The listOfLists.stream() method creates a stream of lists.
  • The flatMap(List::stream) method transforms each list into a stream and flattens the resulting streams into a single stream of elements.
  • The collect(Collectors.toList()) method collects the flattened elements into a list.

Flattening a Stream of Arrays

You can also use flatMap() to flatten a stream of arrays into a single stream.

import java.util.Arrays;
import java.util.stream.Stream;

/**
 * Java 8 - Flattening a Stream of Arrays Using flatMap()
 * Author: https://www.rameshfadatare.com/
 */
public class FlattenStreamOfArrays {

    public static void main(String[] args) {
        // Step 1: Create an array of arrays
        String[][] arrayOfArrays = {
            {"apple", "banana"},
            {"cherry", "date"}
        };

        // Step 2: Flatten the array of arrays using flatMap()
        Stream<String> flattenedStream = Arrays.stream(arrayOfArrays)
            .flatMap(Arrays::stream);

        // Step 3: Display the result
        flattenedStream.forEach(System.out::println);
    }
}

Output

apple
banana
cherry
date

Explanation

  • The Arrays.stream(arrayOfArrays) method creates a stream of arrays.
  • The flatMap(Arrays::stream) method transforms each array into a stream and flattens the resulting streams into a single stream of elements.
  • The forEach(System.out::println) method prints each element in the flattened stream.

Flattening a Stream of Custom Objects

You can also flatten a stream of custom objects that contain collections or arrays. For example, suppose you have a Product class where each product has a list of tags.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Java 8 - Flattening a Stream of Custom Objects Using flatMap()
 * Author: https://www.rameshfadatare.com/
 */
public class FlattenStreamOfCustomObjects {

    public static void main(String[] args) {
        // Step 1: Create a list of products
        List<Product> products = Arrays.asList(
            new Product("Laptop", Arrays.asList("Electronics", "Computers")),
            new Product("Phone", Arrays.asList("Electronics", "Mobile")),
            new Product("Tablet", Arrays.asList("Electronics", "Gadgets"))
        );

        // Step 2: Flatten the tags list using flatMap()
        List<String> allTags = products.stream()
            .flatMap(product -> product.getTags().stream())
            .collect(Collectors.toList());

        // Step 3: Display the result
        System.out.println("All Tags: " + allTags);
    }
}

// Custom class Product
class Product {
    private String name;
    private List<String> tags;

    public Product(String name, List<String> tags) {
        this.name = name;
        this.tags = tags;
    }

    public String getName() {
        return name;
    }

    public List<String> getTags() {
        return tags;
    }
}

Output

All Tags: [Electronics, Computers, Electronics, Mobile, Electronics, Gadgets]

Explanation

  • The products.stream() method creates a stream of Product objects.
  • The flatMap(product -> product.getTags().stream()) method flattens the list of tags for each product into a single stream of tags.
  • The tags are collected into a list using collect(Collectors.toList()).

Advanced Considerations

  • Chaining flatMap() Operations: You can chain multiple flatMap() operations if you have deeply nested structures that need multiple levels of flattening.

  • Performance Considerations: While flatMap() is powerful, it can be computationally intensive with large or deeply nested datasets. Always consider the performance impact when flattening large structures.

  • Handling Null Values: If your nested structures might contain null values, ensure your flatMap() operations handle them appropriately, such as by filtering out nulls before flattening.

Conclusion

This guide provides methods for using flatMap() to flatten streams in Java 8, covering scenarios with lists of lists, arrays of arrays, and custom objects. The flatMap() method is an essential part of the Stream API, allowing you to transform and simplify complex nested structures into a single, manageable stream. By mastering flatMap(), you can handle complex data processing tasks more effectively in your Java applications.

Leave a Comment

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

Scroll to Top