Java Stream flatMap()

Java 8 Stream.flatMap() method is used to flatten a Stream of collections to a Stream of objects. During the flattening operation, the objects from all the collections in the original Stream are combined into a single collection

Stream<Collection<Item>> —-> flatMap() —-> Stream<Item>

List<List<Integer>> listOfLists = Arrays.asList(
  Arrays.asList(1, 2, 3),
  Arrays.asList(4, 5),
  Arrays.asList(6, 7, 8)
);

List<Integer> flattenedList = listOfLists.stream()
  .flatMap(list -> list.stream())  // Flattening step
  .toList();

//Prints [1, 2, 3, 4, 5, 6, 7, 8]
System.out.println("Flattened list: " + flattenedList);

1. What is Flattening?

Imagine we have a bunch of boxes, and each box contains some items. Now, we want to take out all those items from the boxes and put them in a single box. That’s what flatMap() does with a stream. It takes objects from different collections in this stream A and puts all objects in a new Stream B.

In layman’s terms, flattening is referred to as merging multiple collections/arrays into one. Consider the following example.

In this example, we have an array of 3 arrays. After the flattening effect, we will have one result array with all the items from the 3 arrays.

Before flattening 	: [[1, 2, 3], [4, 5], [6, 7, 8]]

After flattening 	: [1, 2, 3, 4, 5, 6, 7, 8]

In the following example, lines is a stream of lines in the file. Each line consists of multiple words. The words stream is a fattened version of all streams into a single stream – consisting of all the words in all the lines.

Path path = ...;  //File Path

Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);

Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));

2. Stream flatMap() Method

2.1. Method Syntax

The stream flatMap() method has the following syntax.

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
  • R represents the element type of the new stream.
  • mapper is a non-interfering, stateless function to apply to each element which produces a stream of new values.
  • The method returns a new stream of objects of type R.

2.2. Features

  • The flatMap() is an intermediate operation and returns a new Stream.
  • It returns a Stream consisting of the results of replacing each element of the given stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
  • The mapper function used for transformation in flatMap() is a stateless function and returns only a stream of new values.
  • Each mapped Stream is closed after its contents have been placed into new Stream.
  • flatMap() operation flattens the stream; opposite to map() operation which does not apply flattening.

3. Stream flatMap() Examples

Example 1: Converting Nested Lists into a Single List

Java 8 example of Stream.flatMap() function to get a single List containing all elements from a list of lists.

This program uses flatMap() operation to convert List<List<Integer>> to List<Integer>.

List<Integer> list1 = Arrays.asList(1,2,3);
List<Integer> list2 = Arrays.asList(4,5,6);
List<Integer> list3 = Arrays.asList(7,8,9);
  
List<List<Integer>> listOfLists = Arrays.asList(list1, list2, list3);
 
List<Integer> listOfAllIntegers = listOfLists.stream()
          .flatMap(x -> x.stream())
          .collect(Collectors.toList());

System.out.println(listOfAllIntegers);

Program output.

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Example 2: Collecting Nested Arrays into a Single List

Java 8 example of Stream.flatMap() function to get a single List containing all elements from an array of arrays.

String[][] dataArray = new String[][]{{"a", "b"}, 
		{"c", "d"}, {"e", "f"}, {"g", "h"}};
         
List<String> listOfAllChars = Arrays.stream(dataArray)
              .flatMap(x -> Arrays.stream(x))
              .collect(Collectors.toList());

System.out.println(listOfAllChars);

Program output.

[a, b, c, d, e, f, g, h]

4. Flattening with IntStream, LongStream and DoubleStream

Stream interface has three more similar methods which produce IntStream, LongStream and DoubleStream respectively that are super helpful if the flattened stream consists only of numeric values such as long, int or doubles.

IntStream flatMapToInt(Function<? super T,? extends IntStream> mapper)
LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper)
DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)

These classes provide convenient methods to perform mathematical operations on all the elements of the Stream, which is often required.

Consider the following example. We have a list of the list of numbers, and we want the sum of all the numbers.

List<List<Integer>> listOfLists = Arrays.asList(
  Arrays.asList(1, 2, 3),
  Arrays.asList(4, 5),
  Arrays.asList(6, 7, 8)
);

int sum = listOfLists.stream()
  .flatMap(list -> list.stream()) // Flatten the list of lists
  .mapToInt(Integer::intValue) // Convert to IntStream
  .sum(); // Calculate the sum

System.out.println("Sum of all numbers: " + sum);  //36

Drop me your questions related to Stream flatMap() example in Java Stream API.

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.