Streams – flatMap() operation

Stream flatMap() in Java is an intermediate operation, and similar to the map() method, it converts/transforms one object into another. We can use the map() method when working with one-level lists or arrays, but if we need to deal with collections containing multiple levels, we will use flatMap().

Stream flatMap() combines the map and flat operations. That means it first applies a function to Stream elements and then flattens the output Stream.

Let’s see some examples to understand it better.

Java Stream flatMap() operation – examples

Let’s see one example using the map() method:

class Test {

  public static void main(String[] args) {
    List<String> cities = new ArrayList<>(Arrays.asList("New York", "Berlin", "Bangkok", "London"));

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

    modifiedList.forEach(System.out::println);
  }
}

Output: NEW YORK BERLIN BANGKOK LONDON

Here, we took the list of Strings and each element we converted to the upper case using the map() method, and then we created a new modified list.

But, what if we have a list of lists? 

List<List<String>> cities = new ArrayList<>();
  cities.add(new ArrayList<>(Arrays.asList("Paris", "London")));
  cities.add(new ArrayList<>(Arrays.asList("New York", "Berlin")));

In this case, we need to use the flatMap() to first flatten the list into one level, and then we can use map() to get the desired result.

Let’s implement the code:

class Test {

  public static void main(String[] args) {
    List<List<String>> cities = new ArrayList<>();
    cities.add(new ArrayList<>(Arrays.asList("Paris", "London")));
    cities.add(new ArrayList<>(Arrays.asList("New York", "Berlin")));

    List<String> modifiedList = cities.stream()
            .flatMap(Collection::stream)
            .map(String::toUpperCase)
            .collect(Collectors.toList());

    modifiedList.forEach(System.out::println);
  }
}

Output: PARIS LONDON NEW YORK BERLIN

We got the same result because the map() function got the flattened stream as input.

Let’s take a closer look at how it works:

class Test {

  public static void main(String[] args) {
    List<List<String>> cities = new ArrayList<>();
    cities.add(new ArrayList<>(Arrays.asList("Paris", "London")));
    cities.add(new ArrayList<>(Arrays.asList("New York", "Berlin")));

    cities.forEach(System.out::println);
  }
}

Output: [[Paris, London], [New York, Berlin]]

We can see from the output that there are two lists inside another.

Now, look at the output after applying the flatMap() operation:

class Test {

  public static void main(String[] args) {
    List<List<String>> cities = new ArrayList<>();
    cities.add(new ArrayList<>(Arrays.asList("Paris", "London")));
    cities.add(new ArrayList<>(Arrays.asList("New York", "Berlin")));

    System.out.println(cities
            .stream()
            .flatMap(Collection::stream)
            .collect(Collectors.toList()));
  }
}

Output: [Paris, London, New York, Berlin]

See how we got a flattened list as a result. So the flatMap() method takes the stream of streams and flattens it to a one-level stream.

I hope this tutorial was helpful to you. To learn more, check out other Java Functional Programming tutorials.

 

Leave a Reply

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