Collect a Stream of Map<K,V> to Map<K,List<V>>

左心房为你撑大大i 提交于 2019-12-30 06:35:10

问题


I have a Stream< Map< K, V > > and I'm trying to merge those maps together, but preserve duplicate values in a list, so the final type would be Map< K, List<V> >. Is there a way to do this? I know the toMap collector has a binary function to basically choose which value is returned, but can it keep track of the converted list?

i.e.

if a is a Stream< Map< String, Int > >

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

回答1:


Use groupingBy: see the javadoc, but in your case it should be something like that:

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

Or:

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



回答2:


This is a bit wordier than the groupingBy solution, but I just wanted to point out that it is also possible to use toMap (as you initially set out to do) by providing the merge function:

    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;
                }));


来源:https://stackoverflow.com/questions/41602519/collect-a-stream-of-mapk-v-to-mapk-listv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!