简体   繁体   English

如何使用java流对作为HashMap值的ArrayList的元素求和?

[英]How to sum elements of an ArrayList which are values of a HashMap using java streams?

I have a HashMap with integer and ArrayList of some Element objects.我有一个带有整数和一些元素对象的 ArrayList 的 HashMap。 Element objects are described with price and amount.元素对象用价格和数量来描述。 I want to go through all those elements in each ArrayList, sum them up by calling on each element element.price() , and create a new HashMap which contains old keys from and new values representing summ of each arraylist.我想遍历每个 ArrayList 中的所有这些元素,通过调用每个元素element.price()总结它们,并创建一个新的 HashMap,其中包含代表每个数组列表总和的旧键和新值。 Keys for new hash map should remain the same.新哈希映射的键应保持不变。 Trying to do this using streams.尝试使用流来做到这一点。

public static HashMap<Integer, Double> findIncomes(HashMap<Integer, ArrayList<Element>> mapa){


    Map<String, Double> m = mapa.entrySet().stream().flatMap()

    return m;
}

The first solution that came to my mind was to use mapToDouble and sum .我想到的第一个解决方案是使用mapToDoublesum

That would have looked like this:那看起来像这样:

public static HashMap<Integer, Double> findIncomes(HashMap<Integer, List<Element>> mapa) {
    HashMap<Integer, Double> sumsByKey = new HashMap<>();
    mapa.entrySet().stream().forEach(entry -> sumsByKey.put(entry.getKey(), entry.getValue().stream().mapToDouble(element -> element.getPrice()).sum()));
    return sumsByKey;
}

But when summing up 1.5d, 5.4d and 6.7d you get 13.600000000000001 as a result.但是当总结 1.5d、5.4d 和 6.7d 时,结果是 13.600000000000001。

Therefore I had to remember: When performing calculations with doubles you usually better use BigDecimal .因此我必须记住:使用双打进行计算时,通常最好使用BigDecimal

So a more accurate solution could look like this:因此,更准确的解决方案可能如下所示:

public static HashMap<Integer, Double> findIncomes(HashMap<Integer, ArrayList<Element>> mapa){
    HashMap<Integer, Double> sumsByKey = new HashMap<>();
    mapa.entrySet().stream().forEach(entry -> sumsByKey.put(entry.getKey(),
        entry.getValue().stream().map(element -> BigDecimal.valueOf(element.getPrice())).reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue()));
    return sumsByKey;
}

Since stream in stream is not really readable it might make sense to refactor it further.由于流中的流并不是真正可读的,因此进一步重构它可能是有意义的。

You need a new map always.你总是需要一张新地图。 You cannot alter the same map with different types.您不能使用不同类型更改同一地图。 Something like this would do the job,像这样的东西可以完成这项工作,

public static HashMap<Integer, Double> findIncomes(HashMap<Integer, ArrayList<Element>> mapa) {

        final HashMap<Integer, Double> m = new HashMap<>();
        mapa.entrySet().stream().forEach(entry -> m.put(entry.getKey(), Double.valueOf(entry.getValue().stream().mapToDouble(Element::price).sum())));
        return m;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM