2017-01-11 26 views
5

Haritaya Harita bir Akış toplayın, ancak bir listede yinelenen değerleri korumak, böylece nihai tip Map< K, List<V> > olurdu. Bunu yapmanın bir yolu var mı? toMap toplayıcısının temel olarak hangi değerin döndüğünü seçmek için ikili bir işlevi olduğunu biliyorum, ancak dönüştürülen listeyi takip edebilir mi? Bir <code>Stream< Map< K, V > ></code> var ve ben birlikte bu haritalar birleştirmek çalışıyorum <K,List<V>>

yani

a bir Stream< Map< String, Int > >

a.flatMap(map -> map.entrySet().stream()).collect(
    Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (val1, val2) -> ?? 
); 

cevap

8

Kullanım groupingBy ise: javadoc görmelerine rağmen durumunda böyle bir şey olmalı:

a.flatMap(map -> map.entrySet().stream()) 
.collect(
    Collectors.groupingBy(
    Map.Entry::getKey, 
    HashMap::new, 
    Collectors.mapping(Map.Entry::getValue, toList()) 
    ) 
); 

Veya:

a.map(Map::entrySet).flatMap(Set::stream) 
.collect(Collectors.groupingBy(
    Map.Entry::getKey, 
    Collectors.mapping(Map.Entry::getValue, toList()) 
    ) 
); 
+3

yapabilirsiniz ['groupingBy (İşlev, Toplayıcı)'] kullanın (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#groupingBy-java.util.function.Function- java.util.stream.Collector-) ve HashMap :: new' dışına çıkın. Ayrıca, yöntem referanslarını tercih edenler için, a.map (Map :: entrySet) .flatMap (Set :: stream) 'komutunu da yapabilirsiniz. – shmosel

+0

Teşekkürler Cevabımı düzenledim. – NoDataFound

0

Bu groupingBy çözümü biraz daha wordier, ama sadece birleştirme işlevini sağlayarak tomap (başlangıçta yapmak için yola gibi) kullanmak da mümkün olduğunu işaret etmek istedim:

a.flatMap(map -> map.entrySet().stream()).collect(
     Collectors.toMap(Map.Entry::getKey, 
       entry -> { 
        List<Integer> list = new ArrayList<>(); 
        list.add(entry.getValue()); 
        return list; 
       }, 
       (list1, list2) -> { 
        list1.addAll(list2); 
        return list1; 
       })); 
İlgili konular