【问题标题】:How merge multiple maps and aggregate values results using Java preferred Java8如何使用 Java 首选 Java8 合并多个映射和聚合值结果
【发布时间】:2016-07-21 17:14:23
【问题描述】:

假设我有多个 N 个带有-> key:string val:Object 的映射

我想将它们全部合并到一张大地图中,并将它们的对象字段值相加:

例如:

import java.util.HashMap;
import java.util.Map;

/**
 * Created by vitaly on 21/07/2016.
 */
public class Merge {

    static Map<String, Container> map1 = new HashMap<>();
    static Map<String, Container> map2 = new HashMap<>();
    static Map<String, Container> map3 = new HashMap<>();


    public void initMaps() {
        map1.put("aaa", new Container(1, "title_aaa"));
        map1.put("bbb", new Container(4, "title_bbb"));

        map2.put("ccc", new Container(7, "title_ccc"));
        map2.put("aaa", new Container(10, "title_aaa"));

        map3.put("aaa", new Container(13, "title_aaa"));
        map3.put("bbb", new Container(16, "title_bbb"));
        ...
        mapN.put(...
    }

    class Container {
        public Container(int val1, String title) {
            this.val1 = val1;
            this.title = title;

        }

        int val1;
        String title;

    }

    public static void main(String[] args) {
        Merge.mergeMaps(map1, map2, map3);
    }

    public static Map<String, Container> mergeMaps(Map... maps) {
        /**
         * HOW create one merged map that sums the values
         */
// The result should be: 
        //map(aaa, {24,title_aaa )   //1+10+13
        //map(bbb, {20,title_ccc )   //4+16
        //map(ccc, {7,title_ccc )   //7
        return map;
    }
}

更喜欢 Java 8 但没关系 :)

非常感谢!

【问题讨论】:

  • putAll 会工作吗?
  • 不要认为它会对“Container”类的值求和
  • 你有什么问题?您似乎没有 mergeMaps 方法。您是否要求一个解决方案来完成您想要完成的所有事情,因为那样看来您自己做的还不够
  • 我已经更新了标题,我正在尝试在合并地图后对值进行总和。 putAll 方法只更新最后一个值

标签: java dictionary hashmap java-8


【解决方案1】:

流过不同的地图,将它们平面映射成一个。然后使用Collectors#groupingBy 通过它们的不同值(aaa、bbb 等)对它们进行排序。 然后再次流式传输此结果以创建具有总和值的新 Container 对象。

最后,使用Collectors.toMap创建你需要的地图。

如果您有任何问题,请不要犹豫。

public static Map<String, Container> mergeMaps(Map<String, Container>... maps) {
    Map<String, Container> map = 
    Arrays.stream(maps)
          .flatMap(x -> x.values().stream())
          .collect(Collectors.groupingBy(v -> v.getTitle().substring(6)))
          .entrySet().stream()
          .map(e -> new Merge().new Container(e.getValue().stream().mapToInt(x -> x.getVal()).sum(), e.getValue().get(0).getTitle()))
          .collect(Collectors.toMap(e -> ((Container) e).getTitle().substring(6), e -> e));

    return map;
}

这是输出

{aaa=24 : title_aaa, ccc=7 : title_ccc, bbb=20 : title_bbb}

【讨论】:

    【解决方案2】:

    使用Map.merge

    private Map<String,Container> mergeContainers(Map<String,Container> a, Map<String,Container> b) {
      Map<String,Container> result = new HashMap<String,Container>(a);
    
      for (Entry<String,Container> entry : b.entrySet()) {
        result.merge(entry.getKey(), entry.getValue(), (aContainer,bContainer) -> MERGE_BOTH_CONTAINERS_HERE); 
      } 
      return result;
    }
    
    private Map<String,Container> mergeContainers(Iterable<Map<String,Container>> maps) {
      return mergeContainers(maps, new HashMap<String,Container>());
    }
    
    private Map<String,Container> mergeContainers(Iterable<Map<String,Container>> maps, Map<String,Container> merged) {
      return maps.hasNext() 
             ? mergeContainers(maps, mergeContainers(merged, maps.next()))
             : merged;
      }
    }
    

    现在在您的代码中,您可以将地图与以下内容合并:

    mergeContainers(Arrays.asList(map1, map2, map3));
    

    【讨论】:

    • 如果我需要使用N个地图...需要调用N次“合并”功能? ...必须更通用的方式..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    • 2020-08-20
    • 1970-01-01
    • 2020-03-19
    • 2019-10-03
    • 1970-01-01
    • 2017-12-10
    相关资源
    最近更新 更多