2016-08-30 3 views
5

내가지도 목록의 형태로 데이터 구조를 설정합니다 : 내가 자바를 사용하여 단일 Set에 목록 (지도의 값)의 모든 요소를 ​​수집 할 List< Map<String, List<String>> >자바 스트림 변환 목록

8 가지 기능.

예 :

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

감사합니다. 최종 collect에 이러한 하위 반복을 융합,이 목적을

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

답변

10

당신은 Stream.mapStream.flatMap의 시리즈를 사용할 수 있습니다 작동 :

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

.flatMap based solutions에 대한 대안에 대한

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> 
    ; 
4

이 문제에 대한 대안이 많이 있습니다. 여기에는 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); 

참고 : 저는 Eclipse Collections에 대한 커미터입니다.