如何使用流

时间:2017-11-16 16:08:25

标签: java java-8 java-stream

我有一组地图:

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;

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

4 个答案:

答案 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)));

哪个更短,更容易,更易读。