我有一组地图:
Collection<Map<String,Double>> myCol = table.values();
我想将其转换为地图
Map<String, Double>
这样,对于匹配的键,将值相加。使用for循环,它很简单:
Map<String, Double> outMap = new HashMap<>();
for (Map<String, Double> map : myCol) {
outMap = mergeMaps(outMap, map);
}
和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;
}
但是,我想使用流来从集合中获取地图。我试过如下:
Map<String, Double> outMap = new HashMap<>();
myCol.stream().forEach(e-> outMap.putAll(mergeMaps(outMap,e)));
return outMap;
这没有问题。但是,我还能改进它吗?我的意思是,我如何在其中使用收藏家?
答案 0 :(得分:5)
根据您的输入,您可以获取地图流,然后将其平面映射为ZRANGE
。从那里,您将它们收集到一个新的地图中,指定您想要将映射到同一个键的值相加。
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));
代替groupingBy
:
toMap
答案 1 :(得分:2)
myCol.stream()
.flatMap(x -> x.entrySet().stream())
.collect(Collectors.groupingBy(
Entry::getKey,
TreeMap::new,
Collectors.summingDouble(Entry::getValue)));
答案 2 :(得分:1)
嗯,其他提出的解决方案显示纯流解决方案很短,但如果你想使用现有的mergeFunction(因为在其他情况下它更复杂),你可以把它交给{{1 }}:
Stream.reduce
你使用forEach的初始方法几乎是一个流线型的循环,违反了没有副作用的函数的概念。 reduce(或以上收集)处理内部合并的所有数据,而不更改输入集合。
答案 3 :(得分:1)
使用流:
Map<String, Double> outMap = myCol.stream()
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(
Map.Entry::getKey, // key of the result map
Map.Entry::getValue, // value of the result map
Double::sum, // how to merge values for equal keys
TreeMap::new)); // the type of map to be created
这使用Collectors.toMap
来创建结果TreeMap
。
但是你可以在没有溪流的情况下做到这一点。我认为你的版本有点复杂,你可以按如下方式重构:
Map<String, Double> outMap = TreeMap<>();
myCol.forEach(map -> map.forEach((k, v) -> outMap.merge(k, v, Double::sum)));
哪个更短,更容易,更易读。