2017-01-11 81 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; 
       })); 
相关问题