Sunday, July 24, 2022

Java 8 - Stream FlatMap Example - List of Lists to List

The flatmap is an interesting concept of functional programming which allows you to flatten the list or stream apart from transforming it, just like the map does. This means you can use the flatmap to flatten the stream. If you have used the map() function from the Stream class before then you can use it to convert an object of type T to another object of Type S. For example, if you have a list of Authors then you can convert it to a List of books by transforming authors to books. FlatMap extends this idea, it not only transform one object to other it also flattens the list and that's it's very useful where you want to know about a combined data set. 

For example, you have an Author object which holds a set of books and you have a list of authors. Now, you want to know all the books written by all these authors. You cannot combine the list of books from each other to get all the books because if you combine them you will get a list of List and not a single big list. 

You need to use a flatMap function here to convert the Author to Book and also flatten two lists into one. That's also the main difference between map and flatMap in Java 8. 

Map function just transforms one object to another but flatmap both transforms and flattens the list, but it's easier said than done. You won't understand map and flatmap until you use them by yourself and that's why I am going to show you two simple examples of flatMap function in Java 8. 

These examples are very common e.g. convert a list of Lists into a single big list and will not only be useful in understanding how flatmap works but also in your day-to-day programming. Btw, if you haven't started Java 8 yet, then you better first check these Java 8 Functional programming courses to get yourself familiar with essential Java 8 concepts like lambda expressions and Stream API. 




Java 8 FlatMap Example 1 - list of Lists

This is one of the simplest examples of flatmap in Java 8. As I said before, flatMap can do two things, it can transform objects just like a map and it can also flatten a list or Stream. That's why you can use it to convert a list of lists into just a list. 

Java 8 - Stream FlatMap Example - List of Lists to List


In this program, I have three lists of numbers containing even numbers, odd numbers, and prime numbers. Now, I need just a list of numbers that contains all the numbers from the above lists.

For that, you can create a List of lists and add all those lists into that. After that, you can just use flatMap to flatten the list as shown below. 

package tool;

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


/**
* 
* A simple Java Program to demonstrate how to 
* use flatMap function of Java 8.
* 
* In this program, we'll convert a list of list
* into just list of elements. 
*/
public class Hello {

public static void main(String[] args) {

// list of even numbers
List<Integer> even = Arrays.asList( 2, 4, 6, 8, 10);

// list of odd numbers
List<Integer> odd = Arrays.asList( 3, 5, 7, 9, 11);

// list of prime numbers
List<Integer> primes = Arrays.asList(17, 19, 23, 29, 31);


// list of numbers
List<List<Integer>> listOfNumbers = new ArrayList<>();
listOfNumbers.add(even);
listOfNumbers.add(odd);
listOfNumbers.add(primes);

System.out.println("list of numbers: " + listOfNumbers);


// above list is not really a list of numbers but a list of list
// to convert that into a list of numbers we will use
// the flatMap function

List<Integer> flattenedList 
     = listOfNumbers.stream()
                    .flatMap(l -> l.stream())
                    .collect(Collectors.toList());

System.out.println("list of numbers (flattend) : " + flattenedList);
}

}

Output
list of numbers: [[2, 4, 6, 8, 10], [3, 5, 7, 9, 11], [17, 19, 23, 29, 31]]
list of numbers (flattend) : [2, 4, 6, 8, 10, 3, 5, 7, 9, 11, 17, 19, 23, 29, 31]




Java 8 Stream FlatMap Example 2 

Here is another example to understand how the flatMap function works in Java 8 or when can you use it. In this case, we have an Author object which contains a set of books written by him. 

In our application we have a list of such authors, we have two for simplicity, Joshua Bloch and Uncle Bob Martin. Now, I need all the books written by them. For this purpose, I can use the flatMap function.

First, I can get a stream of authors from the list then I can transform author to books by calling the getBook() method and flatten the list returned by this method. 

The end result is a list of books. Since we don't want duplicate books, I have collected the result in a Set by using the Collectors.toSet() method. 

package tool;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* 
* A simple Java Program to demonstrate how to use flatMap function of Java 8.
* 
* In this program, we'll convert a set of authors into a set of books written by them. 
*/
public class Hello {

public static void main(String[] args) {

List<Author> listOfAuthors = new ArrayList<>();

Author joshBloch = new Author("Joshua Bloch");
joshBloch.add("Effective Java");
joshBloch.add("Java Puzzlers");;

Author uncleBob = new Author("Robert C. Martin");
uncleBob.add("Clean Code");
uncleBob.add("Clean Coder");
uncleBob.add("Clean Architecure");


listOfAuthors.add(joshBloch);
listOfAuthors.add(uncleBob);

Set<String> books = listOfAuthors.stream()
.flatMap(author -> author.getBooks().stream())
.collect(Collectors.toSet());

System.out.println("List of Books from all the authors");
System.out.println(books);

}

}

class Author {

private final String name;
private final Set<String> books;

public Author(String name) {
this.books = new HashSet<>();
this.name = name;
}

public void add(String book) {
this.books.add(book);
}

public Set<String> getBooks() {
return books;
}
}


Output:
List of Books from all the authors
[Java Puzzlers, Effective Java, Clean Code, Clean Coder, Clean Architecure]


You can see the final set contains all the books written by Joshua Bloch and Uncle Bob Martin including Effective Java and Clean Code, two of my favorite books. 




Important points about FlatMap in Java 8


1. The flatMap function is defined in the java.util.Stream class. 

2. The formal method signature looks like below:

flatMap(Function<? super T? extends Stream<? extends R>> mapper)

This means it accepts a function which both transforms and provides a stream. It then returns a Stream which consists 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.

3. There are a couple of the specialized versions of flatMap function in Stream API which produce specialized stream like flatMapToInt() produces an IntStram, flatMapToLong produces a LongStream, and flatMapToDouble produces a DoubleStream. 

4. You can use the flatMap function to convert a list of lists to a big list containing all elements from individual lists. 

5. Similar to the map function, flatMap is also an intermediate operation which means you can call other stream methods after calling this one. 


That's all about using Stream's flatMap function in Java 8. We have seen two examples to learn how to use the flatMap function for both transformation and flattening of a List of Lists. That's the primary use of FlatMap but you are free for more creative uses as it's very powerful and can solve many common problems you face in your day-to-day coding. 

Related Java 8 Lambda and Stream Tutorials from Javarevisited Blog
  • How to implement Comparator using lambda expression (see here)
  • How to filter Collection using Streams in Java 8 (check here)
  • 20 Examples of Date and Time in Java 8 (tutorial)
  • Top 5 Books to Learn Java 8 (read here)
  • How to use Stream class in Java 8 (tutorial)
  • How to use filter() method in Java 8 (tutorial)
  • How to use forEach() method in Java 8 (example)
  • How to use Stream API in Java 8 (learn here)
  • Understanding Default methods of Java 8 (learn here)
  • How to join String in Java 8 (example)
  • How to convert List to Map in Java 8 (solution)
  • How to use peek() method in Java 8 (example)
  • 8 Best Lambda and Functional Programming courses (best courses)

Thanks for reading this article so far. If you like these Java 8 FlatMap examples then please share them with your friends and colleagues. If you have any questions or feedback about this Java 8 tutorial then please drop a note.

P.S.: If you want to learn more about Lambda, Stream, and other new features in Java 8 then please see these best Java 8 to Java 16 courses. It explains all important features of Java 8 like lambda expressions, streams, functional interface, Optional, new date, and time API, and other miscellaneous changes. 

2 comments:

  1. Can you please give an example of Optional + FlatMap + Collector in Java? I have a method which return a Optional which contains a List of object and I need to collect them into a Map

    ReplyDelete
  2. Can you please give an example of Optional + FlatMap + Collector in Java? I have a method which return a Optional which contains a List of object and I need to collect them into a Map

    ReplyDelete