Java 8: fusionar listas con la API de transmisión


80

Tengo la siguiente situación

Map<Key, ListContainer> map; 

public class ListContainer{
  List<AClass> lst;
}

Tengo que fusionar todas las listas lstde los ListContainerobjetos de un Mapmapa.

public static void main(String args[]){
   List<AClass> alltheObjectsAClass = map.values().stream(). // continue....    
}

¿Alguna idea de cómo usar la API de flujo de Java 8?


¿Puede dar un ejemplo de lo que quiere decir con la fusión? Supongamos que su mapa es {a: [1,2], b[3,4]}, ¿desea encadenarlos, hacer me gusta [1,2,3,4], hacer una lista de listas [[1,2],[3,4]]o comprimirlos [[1,3],[2,4]]? Además, eres consciente de que un mapa no tiene orden, ¿verdad?
tobias_k

@tobias_k ¡Quiero que el resultado sea [1,2,3,4]sin clasificar!
mat_boy

Si ListContainersolo envuelve a List<T>, puede reemplazarlo Map<Key, ListContainer>conMap<Key, List<T>>
ThePyroEagle

Respuestas:


169

Creo que flatMap()es lo que estás buscando.

Por ejemplo:

 List<AClass> allTheObjects = map.values()
         .stream()
         .flatMap(listContainer -> listContainer.lst.stream())
         .collect(Collectors.toList());

2
? ¿Por qué se eliminaron los comentarios que explicaban por qué .flatMap(Collection::stream)no es posible aquí?
Puce

@Puce buena pregunta, sin embargo, es posible: si ListContainerestá encapsulado (es decir, tiene un captador para lst), puede descomponerse .flatMap(->)en.map(ListContainer::getLst) .flatMap(Collection::stream)
TWiStErRob

3
@TWiStErRob Sí, eso es lo que escribí en mi comentario original. ¿Por qué fue eliminado?
Puce

@Poner una nota en su respuesta explicando por qué .flatMap(Collection::stream)no es posible sería mejor, creo. Debería ser más permanente.
SQB

1
@ Alex sí, esta es una forma resp. .map(listContainer -> listContainer.lst).filter(Objects::nonNull).flatMap(Collection::stream)
Puce

55

Alternativa: Stream.concat ()

Stream.concat(map.values().stream(), listContainer.lst.stream())
                             .collect(Collectors.toList()

2
más 1 aunque no responde a la pregunta, responde al título de la pregunta
Tony BenBrahim

2

En Java 8 podemos usar la secuencia List1.stream (). Collect (Collectors.toList ()). AddAll (List2); Otra opción List1.addAll (List2)


1

Ya respondí anteriormente, pero aquí hay otro enfoque que podría tomar. No puedo encontrar la publicación original de la que adapté esto, pero aquí está el código por el bien de su pregunta. Como se señaló anteriormente, la función flatMap () es lo que buscaría utilizar con Java 8. Puede lanzarla en una clase de utilidad y simplemente llamar a "RandomUtils.combine (list1, list2, ...);" y obtendría una única lista con todos los valores. Solo tenga cuidado con el comodín; puede cambiarlo si desea un método menos genérico. También puede modificarlo para conjuntos; solo debe tener cuidado al usar flatMap () en conjuntos para evitar la pérdida de datos de los métodos equals / hashCode debido a la naturaleza de la interfaz de conjunto.

  /**
    * Combines multiple lists into a single list containing all elements of
    * every list.
    * 
    * @param <T> - The type of the lists.
    * @param lists - The group of List implementations to combine
    * @return a single List<?> containing all elements of the passed in lists.
    */
   public static <T> List<?> combine(final List<?>... lists) {
      return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
   }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.