如何使用流合并一组地图

nov*_*ice 7 java java-8 java-stream

我有一组地图:

Collection<Map<String,Double>> myCol = table.values();
Run Code Online (Sandbox Code Playgroud)

我想把它变成一张地图

Map<String, Double>
Run Code Online (Sandbox Code Playgroud)

这样,对于匹配的键,值被加总.使用for循环,它很简单:

Map<String, Double> outMap = new HashMap<>();
for (Map<String, Double> map : myCol) {
    outMap =  mergeMaps(outMap, map);
}
Run Code Online (Sandbox Code Playgroud)

并被mergeMaps()定义为

mergeMaps(Map<String, Double> m1, Map<String, Double> m2){    
    Map<String, Double> outMap = new TreeMap<>(m1);
    m2.forEach((k,v) -> outMap.merge(k,v,Double::sum)); /*sum values if key exists*/
    return outMap;
}
Run Code Online (Sandbox Code Playgroud)

但是,我想使用流来从集合中获取地图.我试过如下:

Map<String, Double> outMap = new HashMap<>();    
myCol.stream().forEach(e-> outMap.putAll(mergeMaps(outMap,e)));
return outMap;
Run Code Online (Sandbox Code Playgroud)

这没有问题.但是,我还能改进它吗?我的意思是,我怎么能在其中使用收藏家?

Ale*_* C. 5

从您的输入中,您可以获取地图流,然后将其平面映射为具有Stream<Map.Entry<String, Double>>.从那里,您将它们收集到一个新映射中,指定您要将映射到同一个键的值相加.

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingDouble;
import static java.util.stream.Collectors.toMap;

....

Map<String, Double> outMap = 
    myCol.stream()
         .flatMap(m -> m.entrySet().stream())
         .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, Double::sum));
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用groupingBy而不是toMap:

.collect(groupingBy(Map.Entry::getKey, summingDouble(Map.Entry::getValue)));
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下`toMap`和`groupingBy`的优点和缺点吗?性能有根本差异吗?从可读性的角度来看,我更喜欢"groupingBy"方法,但这只是我的观点. (2认同)