Wenn ich einen List<List<Object>>
habe, wie kann ich diesen in einen List<Object>
umwandeln, der alle Objekte in derselben Iterationsreihenfolge enthält, indem ich die Funktionen von Java 8 verwende?
Sie können flatMap
verwenden, um die internen Listen (nach der Konvertierung in Streams) in einen einzelnen Stream zu reduzieren und das Ergebnis in einer Liste zusammenzufassen:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
flatmap
ist besser, aber es gibt auch andere Möglichkeiten, dies zu erreichen
List<List<Object>> listOfList = ... // fill
List<Object> collect =
listOfList.stream()
.collect(ArrayList::new, List::addAll, List::addAll);
Die flatMap
-Methode in Stream
kann diese Listen zwar für Sie reduzieren, sie muss jedoch Stream
Objekte für das Element und dann Stream
für das Ergebnis erstellen.
Sie brauchen nicht alle diese Stream
Objekte. Hier ist der einfache, übersichtliche Code zum Ausführen der Aufgabe.
_// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
_
Da List
Iterable
ist, ruft dieser Code die Methode forEach
(Java 8-Funktion) auf, die von Iterable
geerbt wird.
Führt die angegebene Aktion für jedes Element von
Iterable
aus, bis alle Elemente verarbeitet wurden oder die Aktion eine Ausnahme auslöst. Aktionen werden in der Reihenfolge der Iteration ausgeführt, wenn diese Reihenfolge angegeben ist.
Und das List
eines Iterator
gibt Elemente in sequenzieller Reihenfolge zurück.
Für Consumer
übergibt dieser Code eine Methodenreferenz (Java 8-Feature) an die Methode vor Java 8 List.addAll
, um die inneren Listenelemente nacheinander hinzuzufügen.
Hängt alle Elemente in der angegebenen Sammlung an das Ende dieser Liste an, in der Reihenfolge, in der sie vom Iterator der angegebenen Sammlung zurückgegeben werden (optionale Operation).
Sie können das Muster flatCollect()
aus Eclipse Collections verwenden.
MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);
Wenn Sie die Liste von List
nicht ändern können:
List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);
Hinweis: Ich arbeite an Eclipse-Sammlungen mit.
So wie @Saravana es erwähnt hat:
flatmap ist besser, aber es gibt auch andere möglichkeiten, dies zu erreichen
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
Zusammenfassend lässt sich sagen, dass es mehrere Möglichkeiten gibt, dasselbe zu erreichen:
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);
}
Ich möchte nur ein weiteres Szenario wie List<Documents>
erläutern. Diese Liste enthält einige weitere Listen anderer Dokumente wie List<Excel>
, List<Word>
, List<PowerPoint>
. So ist die Struktur
class A {
List<Documents> documentList;
}
class Documents {
List<Excel> excels;
List<Word> words;
List<PowerPoint> ppt;
}
Wenn Sie Excel nur aus Dokumenten iterieren möchten, gehen Sie wie folgt vor.
Also wäre der Code
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.
}
Ich hoffe, dies kann jemandes Problem beim Codieren lösen ...
Methode zum Konvertieren von "Liste von Listen in Liste konvertieren": ListOfLists.stream (). FlatMap (List :: stream) .collect (Collectors.toList ()); Beispiel 1 :
public class ConvertListOfListsToList {
public static void main(String[] args) {
List<String> StringList = Arrays.asList("Protijayi", "Gini", "Gina");
System.out.println(StringList);
List<List<String>> ListOfLists = new ArrayList<>();
ListOfLists.add(StringList);
System.out.println("ListOfLists => " + ListOfLists);
// Now let's do this in Java 8 using FlatMap
List<String> flatMapList = ListOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println("FlatList => " + flatMapList);
/*
ListOfLists => [[Protijayi, Gini, Gina]]
FlatList => [Protijayi, Gini, Gina]
*/
}
}
Eine Erweiterung von Erans Antwort, die die beste Antwort war. Wenn Sie eine Reihe von Listenebenen haben, können Sie diese weiterhin mit einem Flatmapping versehen.
Dies bietet auch eine praktische Möglichkeit zum Filtern, wenn Sie die Ebenen bei Bedarf durchgehen.
Also zum Beispiel:
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())
Dies ist in SQL vergleichbar mit SELECT-Anweisungen in SELECT-Anweisungen.
Wir können Flatmap für diese verwenden, bitte beziehen Sie sich auf den folgenden 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);