How can I turn a List of Lists into a List in Java 8?
If I have a List<List<Object>>
, how can I turn that into a List<Object>
that contains all the objects in the same iteration order by using the features of Java 8?
Solution 1:
You can use flatMap
to flatten the internal lists (after converting them to Streams) into a single Stream, and then collect the result into a list:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
Solution 2:
flatmap
is better but there are other ways to achieve the same
List<List<Object>> listOfList = ... // fill
List<Object> collect =
listOfList.stream()
.collect(ArrayList::new, List::addAll, List::addAll);
Solution 3:
The flatMap
method on Stream
can certainly flatten those lists for you, but it must create Stream
objects for element, then a Stream
for the result.
You don't need all those Stream
objects. Here is the simple, concise code to perform the task.
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
Because a List
is Iterable
, this code calls the forEach
method (Java 8 feature), which is inherited from Iterable
.
Performs the given action for each element of the
Iterable
until all elements have been processed or the action throws an exception. Actions are performed in the order of iteration, if that order is specified.
And a List
's Iterator
returns items in sequential order.
For the Consumer
, this code passes in a method reference (Java 8 feature) to the pre-Java 8 method List.addAll
to add the inner list elements sequentially.
Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator (optional operation).
Solution 4:
Just as @Saravana mentioned:
flatmap is better but there are other ways to achieve the same
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
To sum up, there are several ways to achieve the same as follows:
private <T> List<T> mergeOne(Stream<List<T>> listStream) {
return listStream.flatMap(List::stream).collect(toList());
}
private <T> List<T> mergeTwo(Stream<List<T>> listStream) {
List<T> result = new ArrayList<>();
listStream.forEach(result::addAll);
return result;
}
private <T> List<T> mergeThree(Stream<List<T>> listStream) {
return listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
}
private <T> List<T> mergeFour(Stream<List<T>> listStream) {
return listStream.reduce((l1, l2) -> {
List<T> l = new ArrayList<>(l1);
l.addAll(l2);
return l;
}).orElse(new ArrayList<>());
}
private <T> List<T> mergeFive(Stream<List<T>> listStream) {
return listStream.collect(ArrayList::new, List::addAll, List::addAll);
}