Learnitweb

Stream flatMap() in Java with examples

Method Syntax

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
  • Here, R represents the type of the element of the result Stream.
  • mapper is a stateless function applied on each element of the Stream which produces a new Stream.

Important points about flatMap()

  • Returns a Stream consisting of the results of replacing each element of this Stream with the contents of a mapped Stream produced by applying the provided mapping function to each element.
  • This operation is an intermediate operation and produces another Stream as a result. This operation is always lazy.
  • Each mapped stream is closed after its contents have been placed into this stream. If a mapped stream is null an empty stream is used, instead.
  • The flatMap() operation has the effect of applying a one-to-many transformation to the elements of the stream, and then flattening the resulting elements into a new stream.
  • Stream interface provides three more similar methods. You can use these methods if the requirement is to obtain IntStream, LongStream or DoubleStream.
    • IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper)
    • LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper)
    • DoubleStream flatMapToDouble(Function<? super T, ? extends LongStream> DoubleStream)
  • flatMap() = Flattening + map()

What is flattening?

Let us understand flattening with the help of an example. Consider the following array:

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

After flattening, the result is:

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

So just to understand in simple terms, we can say that flattening is the merging of multiple collections into one.

Need to flat a stream

Sometime there is a need to flat a Stream as it is difficult to process a Stream having more than one level, for example Stream<Stream<String>> or Stream<String[]>. It is easier to loop a Stream having one level of elements like Stream.

Let us see one more example. Suppose we have lists of Strings:

List<String> list1 = Arrays.asList("a","b");
List<String> list2 = Arrays.asList("c","d");

If the requirement is to convert elements of list to uppercase, we first have to merge these lists into one list and then convert each character to uppercase.

We can write the code for the same as:

List<String> list = new ArrayList<>();
list.addAll(l1);
list.addAll(l2);

List<String> rest = list.stream()
			.map(String::toUpperCase)
			.collect(Collectors.toList());

In this code, we have to manually merge the lists and then perform required operation on each element of the list. In this situation, flapMap() can be used to do the same.

Another practical example where flatMap() can be used

Suppose there is a requirement to get words in a page. We can use flatMap() to get a Stream of words in a file.

  • First we get a Stream of lines in a file.
  • We then get Stream of words from a Stream of line using flatMap(). Here, each line will be a Stream having possibly a different number of words.

Stream flatMap() examples

1. Convert nested lists into List using flatMap()

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
  
public class FlatMapExample 
{
    public static void main(String[] args) 
    {
        //create lists
    	List<Integer> list1 = Arrays.asList(1,2,3);
        List<Integer> list2 = Arrays.asList(4,5,6);
        List<Integer> list3 = Arrays.asList(7,8,9);
          
        //create list of lists from lists
        List<List<Integer>> listOfLists = Arrays.asList(list1, list2, list3);
         
        //get flattedList from list of lists
        List<Integer> flattedList = listOfLists.stream()
                            .flatMap(x -> x.stream())
                            .collect(Collectors.toList());
  
        System.out.println(flattedList);
    }
}

Output

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

2. Convert nested arrays into list using flatMap()

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
  
public class FlatMapExample 
{
    public static void main(String[] args) 
    {
        //nested array
    	String[][] dataArray = new String[][]{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "h", "i"}};
         
        List<String> flattedList = Arrays.stream(dataArray)     // convert array to stream 
                                    .flatMap(x -> Arrays.stream(x)) // flat the stream
                                    .collect(Collectors.toList()); // collect result
  
        System.out.println(flattedList);
    }
}

Output

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