The flattening of a List concept is linked with the Nested Collections concept like a List of Lists. These collections consist of more than one List. To be simple, these collections contain other Lists as their elements, creating a nested or hierarchy structure. To simplify the output of these nested collections, you can merge them into a single List (containing the data of all Lists). This process of merging is known as flattening.

This article covers all below mentioned approaches to flatten a List of Lists or Nested Lists in Java:

How to Flatten a List of Lists or Nested List in Java?

Flattening a List means inserting the data of a nested collection/List of Lists into a single parent List without removing any element. The elements are inserted according to their original order and their position in the nested collection. This flattening of a List is performed using many methods which are mentioned below:

Method 1: Flatten a Nested List Using the forEach() and “add()” Methods 

The “forEach()” method allows users to traverse over the Nested List and select each element to perform specific tasks. By combining this method with the “add()” method, the user can add every element of a nested List into a new List. The newly created List then appears as a flattened List:

import java.util.*;
import java.util.stream.Collectors;
//Import the Required Java Packages
class Flattening {
public static void main(String args[])  {
  List<String> Top4 = Arrays.asList("Manchester City", "Real Madrid", "Milan", "Liverpool");
  List<String> Top7 = Arrays.asList("Arsenal", "Bayer", "RB");
  List<String> Countries = Arrays.asList( "Eng", "Spain", "Italy", "Ger", "Eng");
 
  //Creation of the Nested List or List of Lists
  List<List<String>> listOfLists = Arrays.asList(Top4, Top7, Countries);

  List<String> flattened = new ArrayList<String>();
  List<String> tempList = new ArrayList<>();

  //Performing Flattening
    for (List<String> list : listOfLists) {
    list.stream()
    .forEach(tempList::add);
  }

  //Inserting Flattened Result Into List
  flattened = tempList.stream().collect(Collectors.toList());
  System.out.println("Original List of Lists/Nested collection: \n" + listOfLists);
  System.out.println("\nModified Flattened List: \n" + flattened);
}
}

The above code works like this:

  • First, create three “String” type Lists using the “Arrays.asList()” method. Also, create a nested List or List of Lists by inserting the created three Lists into a single List named “listOfLists”. 
  • Next, declare two “String” type Lists named “flattened” and “tempList” using the ArrayList class.
  • Then, utilize the enhanced “for loop” and make it iterated over the “listOfLists” nested List. In it, apply the “stream()” method to place the List elements over the stream. 
  • Also, attach the “forEach()” method to apply the “add()” method on each element and store the result of this method in the “tempList” List.
  • After that, apply the “stream()” and “collect()” methods over the “tempList” List to convert the flattened data into a List. 
  • Finally, store the result in a “flattened” List and print it on the console along with the original nested List.

The output shows that the created Nested List is now flattened:

Method 2: Flatten a Nested List Using “flatMap()” Method

The “flatMap()” method of Stream API is solely used to flatten nested Lists or Streams of data. It accepts an intermediate Lambda expression that returns the flattening results on the console:

import java.util.*;
import java.util.stream.Collectors;

class Flattening {
public static void main(String args[])  {
  List<String> Top4 = Arrays.asList("Manchester City", "Real Madrid", "Milan", "Liverpool");
  List<String> Top7 = Arrays.asList("Arsenal", "Bayer", "RB");
  List<String> Countries = Arrays.asList( "Eng", "Spain", "Italy", "Ger", "Eng");
 
  //Creation of the Nested List or List of Lists
  List<List<String>> listOfLists = Arrays.asList(Top4, Top7, Countries);

  //Performing Flattening
  List<String> flattened = listOfLists.stream()
.flatMap(listItem -> listItem.stream())
.collect(Collectors.toList());

  System.out.println("Original List of Lists/Nested collection: \n" + listOfLists);
  System.out.println("\nModified Flattened List: \n" + flattened);
}
}

In the above code block:

  • First, apply the “stream()” method on the “ListofLists” nested List to place the List element over the Stream.
  • Then, attach the “flatMap()” which contains a Lambda expression to perform the flattening and return the result as a Stream. 
  • Finally, convert the result into a List using the “collect()” method and store it in the “flattened” List. 

Output:

Method 3: Flatten a Nested List Using “reduce()” Method

The “reduce()” method runs a reducer callback function iteratively over all nested List elements and places the result in a single List. In our case scenario, the callback function performs the “addAll()” method over the elements of a “List of Lists” to combine and place them in a single List:

import java.util.*;
class Flattening {
public static void main(String args[])  {
  List<String> Top4 = Arrays.asList("Manchester City", "Real Madrid", "Milan", "Liverpool");
  List<String> Top7 = Arrays.asList("Arsenal", "Bayer", "RB");
  List<String> Countries = Arrays.asList( "Eng", "Spain", "Italy", "Ger");
  List<List<String>> listOfLists = Arrays.asList(Top4, Top7, Countries);

  //Performing Flattening
  List<String> flattened = listOfLists.stream()
  .reduce(new ArrayList<>(), (list1, list2) -> {
    list1.addAll(list2);
    return list1;
  });

  System.out.println("Original List of Lists/Nested collection: \n" + listOfLists);
  System.out.println("\nModified Flattened List: \n" + flattened);
}
}

In the above code snippet:

  • First, create a nested List named “ListOfLists” by combining three “String” type Lists using the “Arrays.asList()” method.
  • Next, apply the “reduce()” method of Stream API along with its reducer callback function over the “ListOfLists”. This callback function uses the “addAll()” method to add all the elements of the containing Lists into a list named “ListOfLists”. 
  • The resultant List is then returned by this function as a Flatten List.

The output confirms the flattening of a ListOfLists using the “reduce()” method:

Method 4: Flatten a Nested List Using “collect()” Method

The “collect()” method works properly on all versions above 8. The “collect()” method of Stream API allows users to flatten the Nested List while consuming minimum lines of code:

import java.util.*;

class Flattening {
public static void main(String args[])  {
  List<String> Top4 = Arrays.asList("Manchester City", "Real Madrid", "Milan", "Liverpool");
  List<String> Top7 = Arrays.asList("Arsenal", "Bayer", "RB");
  List<String> Countries = Arrays.asList( "Eng", "Spain", "Italy", "Ger");
  List<List<String>> listOfLists = Arrays.asList(Top4, Top7, Countries);

//Flattening Code
  List<String> flattened = listOfLists.stream()
.collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);

  System.out.println("Original List of Lists/Nested collection: \n" + listOfLists);
  System.out.println("\nModified Flattened List: \n" + flattened);
}
}

The above code works like this:

  • First, create a nested List named “listOfLists” using the “Arrays.asList()” method.
  • Next, apply the “collect()” method over “ListOfLists” after placing its elements over the Stream. Set the “addAll()” method as its mapper argument to add the elements into a new collection. This new collection is “ArrayList” which is created by a “combiner” argument. 
  • Finally, store the result in a “flattened” List and display it on the console.

Output:

Method 5: Flatten a Nested List Using Enhanced For Loop

The “enhanced for” or “For-each” Loop allows users to iterate over the nested collection elements. In our case, this loop is used with the “addAll()” method to flatten the targeted nested List:

import java.util.*;
class Flattening {
public static void main(String args[])  {
  List<String> Top4 = Arrays.asList("Manchester City", "Real Madrid", "Milan", "Liverpool");
  List<String> Top7 = Arrays.asList("Arsenal", "Bayer", "RB");
  List<String> Countries = Arrays.asList( "Eng", "Spain", "Italy", "Ger");

//Creating Nested List
  List<List<String>> listOfLists = Arrays.asList(Top4, Top7, Countries);

  //Performing Flattening
  List<String> flattened = new ArrayList<>();
  for (List<String> list : listOfLists) {
  flattened.addAll(list);
  }
  System.out.println("Original List of Lists/Nested collection: \n" + listOfLists);
  System.out.println("\nModified Flattened List: \n" + flattened);
}
}

The above code works like this:

  • First, create a List of Lists or nested Lists just like we did in the above sections.
  • Next, utilize the enhanced “for” loop to select the nested List elements. After that, add these selected elements into a new List named “flattened” using the “addAll()” method.

Output:

Method 6: Flatten a Nested List Using “Guava” Library

The “Guava” library offers the “Iterables.concat()” to flatten the nested collection like List in Java. To convert this flattened collection into a new List, use the “Lists.newArrayList()” method. 

Prerequisites:

To work with the “Guava” API the user can either create a Maven or Java project and needs to perform below mentioned configurations:

For Maven: Create a new “Maven” project. Then, insert the below-mentioned dependencies inside the project’s auto-created “pom.xml” file:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

For Java: Download the Guava “JAR” File from “Guava Core Libraries” and add it to the “Classpath” of your project.

After the configuration, have a look at the below code example to flatten a nested List:

import java.util.*;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

public class Flattening {
public static void main(String[] args)
{
  List<Double> evenList = Arrays.asList( 2.1, 42.7, 61.9, 8.72, 10.01);
  List<Double> oddList = Arrays.asList( 3.34, 5.12, 7.56, 9.82, 1.1);
  List<Double> primeList = Arrays.asList(1.45, 3.89, 0.05, 7.53, 11.3);

  List<List<Double>> listOfLists = new ArrayList<>();
  listOfLists.add(evenList);
  listOfLists.add(oddList);
  listOfLists.add(primeList);

  System.out.println("Original List of Lists/Nested collection: \n" + listOfLists);

  //Flatten a List Using Guava
  Iterable<Double> iterable = Iterables.concat(listOfLists);
  List<Double> flattened = Lists.newArrayList(iterable);

  System.out.println("\nFlattered List: \n" + flattened);
}
}

The working of the above code is as follows:

  • First, create a nested List “listOfLists” and add three “Double” type Lists into it using the “add()” method.
  • Next, concatenate the “ListOfLists” elements into a single “Iterable” object using the “Iterables.concat()” method. 
  • Finally, pass this “Iterable” object in the “Lists.newArrayList()” method to transform it into a “flattened” List.

Output:

That’s all on the flattening of a List or Nested collections in Java.

Conclusion

To flatten a list of lists or nested List in Java, use the “forEach()” method with the “add()” method, Java 8 Stream API “flatMap()”, “reduce()”, and “collect()” methods. The combination of the enhanced“for” loop and “addAll()” method also performs the flattening over a nested List. Last but not least, use the “Guava” Google library that offers an “Iterables.concat()” method which returns the flattened version of a provided nested list. This guide has explained approaches to flatten the nested List in Java.