If I have a List
, how can I turn that into a >
List
that contains all the objects in the same iteration order
Method to convert a List<List>
to List
:
listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
See this example:
public class Example {
public static void main(String[] args) {
List<List<String>> listOfLists = Collections.singletonList(Arrays.asList("a", "b", "v"));
List<String> list = listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println("listOfLists => " + listOfLists);
System.out.println("list => " + list);
}
}
It prints:
listOfLists => [[a, b, c]]
list => [a, b, c]
We can use flatmap for this, please refer below code :
List<Integer> i1= Arrays.asList(1, 2, 3, 4);
List<Integer> i2= Arrays.asList(5, 6, 7, 8);
List<List<Integer>> ii= Arrays.asList(i1, i2);
System.out.println("List<List<Integer>>"+ii);
List<Integer> flat=ii.stream().flatMap(l-> l.stream()).collect(Collectors.toList());
System.out.println("Flattened to List<Integer>"+flat);
An expansion on Eran's answer that was the top answer, if you have a bunch of layers of lists, you can keep flatmapping them.
This also comes with a handy way of filtering as you go down the layers if needed as well.
So for example:
List<List<List<List<List<List<Object>>>>>> multiLayeredList = ...
List<Object> objectList = multiLayeredList
.stream()
.flatmap(someList1 -> someList1
.stream()
.filter(...Optional...))
.flatmap(someList2 -> someList2
.stream()
.filter(...Optional...))
.flatmap(someList3 -> someList3
.stream()
.filter(...Optional...))
...
.collect(Collectors.toList())
This is would be similar in SQL to having SELECT statements within SELECT statements.
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);
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());
I just want to explain one more scenario like List<Documents>
, this list contains a few more lists of other documents like List<Excel>
, List<Word>
, List<PowerPoint>
. So the structure is
class A {
List<Documents> documentList;
}
class Documents {
List<Excel> excels;
List<Word> words;
List<PowerPoint> ppt;
}
Now if you want to iterate Excel only from documents then do something like below..
So the code would be
List<Documents> documentList = new A().getDocumentList();
//check documentList as not null
Optional<Excel> excelOptional = documentList.stream()
.map(doc -> doc.getExcel())
.flatMap(List::stream).findFirst();
if(excelOptional.isPresent()){
Excel exl = optionalExcel.get();
// now get the value what you want.
}
I hope this can solve someone's issue while coding...