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
Iterablejusqu'à 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..