Comment puis-je transformer une liste de listes en une liste dans Java 8?
Si j'ai un List<List<Object>>
, comment puis-je le transformer en un List<Object>
qui contient tous les objets dans la même itération de commande en utilisant les fonctionnalités de Java 8?
6 réponses
Vous pouvez utiliser flatMap
pour aplatir le les listes internes (après les convertir en Flux) en un seul Flux, puis recueillir le résultat dans une liste:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
flatmap
c'est mieux mais il y a d'autres façons d'atteindre le même
List<List<Object>> listOfList = ... // fill
List<Object> collect =
listOfList.stream()
.collect(ArrayList::new, List::addAll, List::addAll);
Vous pouvez utiliser le modèle flatCollect()
de Eclipse Collections .
MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);
Si vous ne pouvez pas modifier la liste de List
:
List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);
Remarque: je suis un contributeur aux Collections Eclipse.
Le flatMap
méthode sur Stream
peut certainement aplatir ces listes pour vous, mais il doit créer Stream
objets pour l'élément, puis un Stream
pour le résultat.
Vous n'avez pas besoin de tous ces objets Stream
. Voici le code simple et concis pour effectuer la tâche.
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
Parce qu'un List
est Iterable
, ce code appelle la méthode forEach
(fonctionnalité Java 8), qui est héritée de Iterable
.
Effectue l'action donnée pour chaque élément du
Iterable
jusqu'à ce que tous les éléments ont été traitées ou l'action lève une exception. Les Actions sont effectuées dans l'ordre d'itération, si cet ordre est spécifié.
Et un List
Iterator
renvoie les éléments dans un ordre séquentiel.
Pour le Consumer
, ce code passe dans une référence de méthode (fonctionnalité Java 8) à la méthode pré-Java 8List.addAll
pour ajouter les éléments de liste interne séquentiellement.
Ajoute tous les éléments de la collection spécifiée à la fin de cette liste, dans l'ordre qu'ils sont retournés par l'itérateur de la collection spécifiée (opération facultative).
Tout comme @ Saravana mentionné:
Flatmap est mieux, mais il y a d'autres façons d'atteindre le même
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
Pour résumer, il y a plusieurs façons d'atteindre le même comme suit:
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);
}
Je veux juste expliquer un scénario plus comme List<Documents>
, cette liste contient un peu plus de listes d'autres documents comme List<Excel>
, List<Word>
, List<PowerPoint>
. Donc la structure est
Class A{
List<Documents> documentList
}
Class Documents{
List<Excel> excels
List<Word> words
List<PowerPoint> ppt
}
Maintenant, si vous voulez itérer Excel uniquement à partir de documents, faites quelque chose comme ci-dessous..
Donc le code serait
List<Document> 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.
}
J'espère que cela peut résoudre le problème de quelqu'un pendant le codage..