将Map<K,V>流收集到Map<K,List<V>>中

7
我有一个 `Stream>`,我想把这些 Map 合并在一起,但要保留列表中的重复值,因此最终类型应为 `Map>`。有没有办法做到这一点?我知道 `toMap` 收集器有一个二元函数可以选择返回哪个值,但它能否跟踪转换后的列表呢?
例如,如果 `a` 是一个 `Stream>`:
a.flatMap(map -> map.entrySet().stream()).collect(
    Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (val1, val2) -> ??
);
2个回答

11

使用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),并省略 HashMap::new。此外,对于那些喜欢方法引用的人,你可以使用 a.map(Map::entrySet).flatMap(Set::stream) - shmosel

0

这比groupingBy解决方案更冗长,但我只是想指出,也可以使用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;
                }));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接