2017-01-11 85 views
5

我有一個Stream< Map< K, V > >,我試圖合併這些地圖在一起,但在列表中保留重複的值,所以最終的類型將是Map< K, List<V> >。有沒有辦法做到這一點?我知道toMap收集器有一個二元函數來基本上選擇返回哪個值,但它可以跟蹤轉換後的列表嗎?收集地圖流<K,V>到地圖<K,List<V>>

如果aStream< Map< String, Int > >

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

回答

8

使用groupingBy:看的javadoc,但在你的情況下,它應該是類似的東西:

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

或者:

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

你可以使用['groupingBy(Function,Collector)'](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#groupingBy-java.util.function.Function- java.util.stream.Collector-)並省略'HashMap :: new'。另外,對於喜歡方法引用的用戶,可以執行'a.map(Map :: entrySet).flatMap(Set :: stream)'。 – shmosel

+0

謝謝我編輯了我的答案。 – NoDataFound

0

這比groupingBy解決方案wordier了一點,但我只是想指出的是,還可以通過提供合併功能使用toMap(如您最初着手去做):

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; 
       })); 
相關問題