Flatten a List of Lists in Java
This post will discuss how to flatten a List of Lists in Java. In other words, convert a List<List<T>> into a List<T> in Java.
1. Using Stream.flatMap() method
The standard solution is to use the Stream.flatMap() method to flatten a List of Lists. The flatMap() method applies the specified mapping function to each element of the stream and flattens it.
The following program demonstrates the usage of the flatMap() method to flatten a list of lists:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; class Main { public static<T> List<T> flatten(List<List<T>> listOfLists) { return listOfLists.stream() .flatMap(List::stream) .collect(Collectors.toList()); } public static void main(String[] args) { List<List<Integer>> listOfLists = IntStream.rangeClosed(1, 3) .boxed() .map(i -> Collections.nCopies(4, i)) .collect(Collectors.toList()); System.out.println("Original List " + listOfLists); List<Integer> flattenedList = flatten(listOfLists); System.out.println("Flattened List " + flattenedList); } } |
Output:
Original List [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
Flattened List [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
2. Using foreach construct
You don’t need fancy Streams to perform this challenging-looking task. Another alternative is to use a foreach-construct to add elements of each list into a new list, as demonstrated below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; class Main { public static<T> List<T> flatten(List<List<T>> listOfLists) { List<T> result = new ArrayList<>(); for (List<T> listOfList : listOfLists) { result.addAll(listOfList); } return result; } public static void main(String[] args) { List<List<Integer>> listOfLists = IntStream.rangeClosed(1, 3) .boxed() .map(i -> Collections.nCopies(4, i)) .collect(Collectors.toList()); System.out.println("Original List " + listOfLists); List<Integer> flattenedList = flatten(listOfLists); System.out.println("Flattened List " + flattenedList); } } |
Output:
Original List [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
Flattened List [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
This is equivalent to the following Java 8 code using forEach() method:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; class Main { public static<T> List<T> flatten(List<List<T>> listOfLists) { List<T> result = new ArrayList<>(); listOfLists.forEach(result::addAll); return result; } public static void main(String[] args) { List<List<Integer>> listOfLists = IntStream.rangeClosed(1, 3) .boxed() .map(i -> Collections.nCopies(4, i)) .collect(Collectors.toList()); System.out.println("Original List " + listOfLists); List<Integer> flattenedList = flatten(listOfLists); System.out.println("Flattened List " + flattenedList); } } |
Output:
Original List [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
Flattened List [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
3. Using Stream.collect() method
Another Java 8 solution is to perform a mutable reduction operation on the elements of the stream using the collect() method. For example,
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; class Main { public static<T> List<T> flatten(List<List<T>> listOfLists) { return listOfLists.stream() .collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll); } public static void main(String[] args) { List<List<Integer>> listOfLists = IntStream.rangeClosed(1, 3) .boxed() .map(i -> Collections.nCopies(4, i)) .collect(Collectors.toList()); System.out.println("Original List " + listOfLists); List<Integer> flattenedList = flatten(listOfLists); System.out.println("Flattened List " + flattenedList); } } |
Output:
Original List [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
Flattened List [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
4. Using Stream.reduce() method
Another possibility is to perform a reduction operation on the elements of the stream using an associative accumulation function:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; class Main { public static<T> List<T> flatten(List<List<T>> listOfLists) { return listOfLists.stream().reduce((x, y) -> { List<T> list = new ArrayList<>(x); list.addAll(y); return list; }).orElse(new ArrayList<>()); } public static void main(String[] args) { List<List<Integer>> listOfLists = IntStream.rangeClosed(1, 3) .boxed() .map(i -> Collections.nCopies(4, i)) .collect(Collectors.toList()); System.out.println("Original List " + listOfLists); List<Integer> flattenedList = flatten(listOfLists); System.out.println("Flattened List " + flattenedList); } } |
Output:
Original List [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
Flattened List [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
Here’s a better way to do it, using the provided identity value and an associative accumulation function.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; class Main { public static<T> List<T> flatten(List<List<T>> listOfLists) { return listOfLists.stream().reduce(new ArrayList<>(), (x, y) -> { x.addAll(y); return x; }); } public static void main(String[] args) { List<List<Integer>> listOfLists = IntStream.rangeClosed(1, 3) .boxed() .map(i -> Collections.nCopies(4, i)) .collect(Collectors.toList()); System.out.println("Original List " + listOfLists); List<Integer> flattenedList = flatten(listOfLists); System.out.println("Flattened List " + flattenedList); } } |
Output:
Original List [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
Flattened List [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
That’s all about flattening a List of Lists in Java.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)