2016-08-30 20 views
5

mam struktury danych w formie listy map: List< Map<String, List<String>> >Java strumień lista Konwersja map ustawić

Chcę zebrać wszystkie elementy listy (wartości map) w jednym Set używając Java 8 funkcji.

przykład:

Input: [ {"a" : ["b", "c", "d"], "b" : ["a", "b"]}, {"c" : ["a", "f"]} ] 
Output: ["a", "b", "c", "d", "f"] 

Dzięki.

Odpowiedz

10

można wykorzystywać szereg Stream.map i Stream.flatMap:

List<Map<String, List<String>>> input = ...; 

Set<String> output = input.stream() // -> Stream<Map<String, List<String>>> 
    .map(Map::values)     // -> Stream<List<List<String>>> 
    .flatMap(Collection::stream)  // -> Stream<List<String>> 
    .flatMap(Collection::stream)  // -> Stream<String> 
    .collect(Collectors.toSet())  // -> Set<String> 
    ; 
5

Zastosowanie flatMap do tego celu

List< Map<String, List<String>> > maps = ... 
Set<String> result = maps.stream() 
         .flatMap(m -> m.values().stream()) 
         .flatMap(List::stream) 
         .collect(Collectors.toSet()); 
4

Alternatywą dla .flatMap based solutions jest do fuzji tych sub-iteracji do finału collect operacja:

Set<String> output = input.stream() 
    .collect(HashSet::new, (set,map) -> map.values().forEach(set::addAll), Set::addAll); 
4

Istnieje wiele alternatyw dla tego problemu. Oto kilka z dwóch innych odpowiedzi dostarczonych z użyciem kontenerów Eclipse Collections.

MutableList<MutableMap<String, MutableList<String>>> list = 
     Lists.mutable.with(
       Maps.mutable.with(
         "a", Lists.mutable.with("b", "c", "d"), 
         "b", Lists.mutable.with("a", "b")), 
       Maps.mutable.with(
         "c", Lists.mutable.with("a", "f"))); 

ImmutableSet<String> expected = Sets.immutable.with("a", "b", "c", "d", "f"); 

// Accepted Streams solution 
Set<String> stringsStream = list.stream() 
     .map(Map::values) 
     .flatMap(Collection::stream) 
     .flatMap(Collection::stream) 
     .collect(Collectors.toSet()); 
Assert.assertEquals(expected, stringsStream); 

// Lazy Eclipse Collections API solution 
MutableSet<String> stringsLazy = list.asLazy() 
     .flatCollect(MutableMap::values) 
     .flatCollect(e -> e) 
     .toSet(); 
Assert.assertEquals(expected, stringsLazy); 

// Eager Eclipse Collections API solution 
MutableSet<String> stringsEager = 
     list.flatCollect(
       map -> map.flatCollect(e -> e), 
       Sets.mutable.empty()); 
Assert.assertEquals(expected, stringsEager); 

// Fused collect operation 
Set<String> stringsCollect = list.stream() 
     .collect(
       HashSet::new, 
       (set, map) -> map.values().forEach(set::addAll), 
       Set::addAll); 
Assert.assertEquals(expected, stringsCollect); 

// Fused injectInto operation 
MutableSet<String> stringsInject = 
     list.injectInto(
       Sets.mutable.empty(), 
       (set, map) -> set.withAll(map.flatCollect(e -> e))); 
Assert.assertEquals(expected, stringsInject); 

Uwaga: jestem uczestnikiem kolekcji Eclipse.