【问题标题】:How to sum elements of an ArrayList which are values of a HashMap using java streams?如何使用 java 流对 ArrayList 的元素求和,这些元素是 HashMap 的值?
【发布时间】:2019-08-20 09:29:06
【问题描述】:

我有一个带有整数的 HashMap 和一些 Element 对象的 ArrayList。元素对象用价格和数量来描述。我想遍历每个 ArrayList 中的所有这些元素,通过调用每个元素 element.price() 来总结它们,并创建一个新的 HashMap,其中包含来自每个数组列表的旧键和表示总和的新值。新哈希映射的键应该保持不变。尝试使用流来做到这一点。

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


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

    return m;
}

【问题讨论】:

  • HashMap 可能没有排序。
  • HashMaps 无法被索引,因此对其元素进行排序没有意义。如果你想要一个排序的地图,可以考虑 TreeMap。
  • TreeMap 按键排序,而不是按值排序。你不应该使用地图,不管它是什么类型的。
  • HashMap 实现为哈希表,键或值没有排序。 TreeMap是基于红黑树结构实现的,按key排序。 LinkedHashMap 保留插入顺序。 Hashtable 是同步的,与 HashMap 不同。
  • 为什么不首先使用List 而不是Map

标签: java lambda hashmap java-stream


【解决方案1】:

我想到的第一个解决方案是使用mapToDoublesum

应该是这样的:

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;
}

但是当将 1.5d、5.4d 和 6.7d 相加时,结果是 13.600000000000001。

因此我必须记住:使用双精度进行计算时,您通常最好使用BigDecimal

所以更准确的解决方案可能如下所示:

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;
}

由于流中的流不是真正可读的,因此进一步重构它可能是有意义的。

【讨论】:

  • 为什么需要 BigDecimal 进行求和?
  • 第4行@MaS,你为什么用map(),可以用mapToDouble()吗?
  • 因为我想将元素的价格映射到 BigDecimal 我不能使用 mapToDouble。
  • 您能否详细解释一下您使用 BigDecimal 处理的精度部分?我完全不明白:-)
  • @Miljan reduce-call 或多或少地执行了随后的 add-calls 以获得单个结果(=总和)。
【解决方案2】:

您总是需要一张新地图。您不能使用不同类型更改同一地图。像这样的东西可以完成这项工作,

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;
    }

【讨论】:

    猜你喜欢
    • 2012-01-01
    • 2013-04-20
    • 1970-01-01
    • 2014-01-29
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多