si tengo un List<List<Object>>
¿cómo puedo convertir eso en un List<Object>
que contiene todos los objetos en el mismo orden de iteración usando las funciones de Java 8?
¿Cómo puedo convertir una lista de listas en una lista en Java 8?
Sara Szabo
Eran
Puedes usar flatMap
para aplanar las listas internas (después de convertirlas en Streams) en un solo Stream y luego recopilar el resultado en una lista:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
-
@arshajii cierto, pero por alguna razón prefiero la expresión lambda. Tal vez no me gusta el aspecto de
::
🙂– Eran
5 de agosto de 2014 a las 19:55
-
Class::method
se siente un poco extraño al principio, pero tiene la ventaja de que declara de qué tipo de objeto se está mapeando. Eso es algo que de otro modo perderías en las transmisiones.– ArneHugo
15 de marzo de 2016 a las 15:13
-
Sin embargo, es posible que desee tener un contenedor de una Lista y, en ese caso, es posible que deba usar la lambda (l->l.myList.stream()).
– Mioquia
22 de diciembre de 2016 a las 10:18
-
Si necesita hacer una conversión explícita (una matriz de primitivas a la Lista, por ejemplo), también puede ser necesario lambdas.
–Michael Fulton
28 de mayo de 2017 a las 3:58
-
funcionó para mí gracias
–Mugeesh Husain
14 de enero a las 3:48
Saravana
flatmap
es mejor pero hay otras formas de lograr lo mismo
List<List<Object>> listOfList = ... // fill
List<Object> collect =
listOfList.stream()
.collect(ArrayList::new, List::addAll, List::addAll);
-
Tenga en cuenta que al usar flatMap no cerrará la transmisión, ya que con la recopilación deberá volver a abrirla.
– Georgi Peev
10 mayo 2021 a las 10:53
los flatMap
método en Stream
ciertamente puede aplanar esas listas para usted, pero debe crear Stream
objetos por elemento, luego un Stream
por el resultado
No necesitas todos esos Stream
objetos. Aquí está el código simple y conciso para realizar la tarea.
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
Porque un List
es Iterable
este código llama los forEach
método (característica de Java 8), que se hereda de Iterable
.
Realiza la acción dada para cada elemento del
Iterable
hasta que todos los elementos hayan sido procesados o la acción arroje una excepción. Las acciones se realizan en el orden de iteración, si se especifica ese orden.
y un List
‘s Iterator
devuelve elementos en orden secuencial.
Para el Consumer
este código pasa una referencia de método (característica de Java 8) al método anterior a Java 8 List.addAll
para agregar los elementos de la lista interna secuencialmente.
Agrega todos los elementos de la colección especificada al final de esta lista, en el orden en que los devuelve el iterador de la colección especificada (operación opcional).
-
Buena sugerencia alternativa que evita algunas asignaciones innecesarias. Sería interesante ver el uso del montón superior de esto cuando se trabaja con algunas colecciones más grandes, para ver cómo se comparan entre sí.
– Por Lundberg
10 de julio de 2019 a las 12:51
Soudipta Dutta
Método para convertir un List<List>
para List
:
listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
Mira este ejemplo:
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);
}
}
Imprime:
listOfLists => [[a, b, c]]
list => [a, b, c]
En Python, esto se puede hacer usando Comprensión de listas.
list_of_lists = [['Roopa','Roopi','Tabu', 'Soudipta'],[180.0, 1231, 2112, 3112], [130], [158.2], [220.2]]
flatten = [val for sublist in list_of_lists for val in sublist]
print(flatten)
['Roopa', 'Roopi', 'Tabu', 'Soudipta', 180.0, 1231, 2112, 3112, 130, 158.2, 220.2]
Tal como lo mencionó @Saravana:
flatmap es mejor pero hay otras formas de lograr lo mismo
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
En resumen, hay varias formas de lograr lo mismo de la siguiente manera:
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);
}
Solo quiero explicar un escenario más como List<Documents>
esta lista contiene algunas listas más de otros documentos como List<Excel>
, List<Word>
, List<PowerPoint>
. Entonces la estructura es
class A {
List<Documents> documentList;
}
class Documents {
List<Excel> excels;
List<Word> words;
List<PowerPoint> ppt;
}
Ahora, si desea iterar Excel solo desde documentos, haga algo como a continuación.
entonces el codigo seria
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.
}
Espero que esto pueda resolver el problema de alguien mientras codifica…
Nikhil Nanivadekar
Puedes usar el flatCollect()
patrón de Colecciones de Eclipse.
MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);
Si no puede cambiar la lista de List
:
List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);
Nota: Soy colaborador de Eclipse Collections.
-
¿Por qué usar una dependencia de terceros cuando Java 8 proporciona la funcionalidad?
– sierra303
20 de octubre de 2017 a las 8:34
-
Eclipse Collections API está en la colección en sí, por lo que el código es conciso, es una de las razones principales en este caso.
– Nikhil Nanivadekar
21 oct 2017 a las 18:18