【问题标题】:Elegant and performant way to aggregate multiple Maps to a single one将多个地图聚合到一个地图的优雅而高效的方式
【发布时间】:2019-05-15 08:21:54
【问题描述】:

我有一个地图列表。所有地图都有相同的键。现在我想通过汇总每个键的值来将列表的所有地图聚合到一个地图。

感觉应该有更好的方法来做到这一点。

// source
public List<Map<Integer, Long>> list_of_maps = new ArrayList<>();

// destination
private Map<Integer, Long> aggr_map = new HashMap<>();


for(Integer i : list_of_maps.iterator().next().keySet()){
    long c = 0;
    for(Map<Integer, Long> map : list_of_maps){
        c += map.get(i).getCount();
    }
    aggr_map.put(i, c);
}

我经常运行这个聚合,所以运行时真的很重要...

【问题讨论】:

  • Counter/numRecordsEachSubpartition 是从哪里来的?
  • 如果性能是最重要的考虑因素,我会坚持使用您现在拥有的解决方案,而不是使用有一些开销的 Streams。
  • 我假设aggr_mapnumRecordsEachSubpartition 应该是相同的Map,对吧?
  • sry,我混淆了命名 -.- 现在修复它!
  • aggr_map 是否需要是全新的地图,或者是否可以将元素添加到列表中的现有地图之一?

标签: java dictionary java-8 hashmap


【解决方案1】:

你可以这样做,

Map<Integer, Long> numToSumMap = list_of_maps.stream()
    .flatMap(m -> m.entrySet().stream())
    .collect(Collectors.groupingBy(Map.Entry::getKey, 
        Collectors.summingLong(Map.Entry::getValue)));

【讨论】:

  • 如果不做任何基准测试,我不能说它的性能更高。但这对我来说绝对更具可读性。谈到代码的可读性和可维护性对我们来说至关重要。
  • 我对性能做了一些小的研究,发现使用流似乎会对性能产生负面影响。见:blog.jooq.org/2015/12/08/…
  • 但是流可以让你并行执行,如果你有大量的工作,这会提高性能。上述基于流的解决方案是并行友好的。
猜你喜欢
  • 1970-01-01
  • 2019-04-01
  • 2014-12-19
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 2019-08-18
  • 2023-03-31
  • 2021-11-30
相关资源
最近更新 更多