【问题标题】:Merging two Map<String,List> [duplicate]合并两个 Map<String,List> [重复]
【发布时间】:2016-11-25 13:05:38
【问题描述】:

我有两个 HashMap,其中键是字符串,值是 ArrayList。我需要以这样的方式合并这两个地图,如果 --

  1. 如果 key 不存在,则应该使用给定的值映射 key。
  2. 如果 key 已经存在,我希望将现有值与新值合并,即 existingList.addAll(newList)。

初始代码有点像 --

为map的所有键检查是否

 if (map1.containsKey("key")){
 List l = map1.get ("key");
 l.addAll(map2.get("key"));
 }
 else{
 map1.put(map2);
 }

我不关心这里的重复元素。有没有一种干净的方法可以做到这一点?我已经阅读了 Java 8 中引入的合并方法。但是由于这里的值是 List 类型,我正在寻找一种更有效和更干净的方法。

【问题讨论】:

  • 我建议您完全按照您描述的方式编写它。然后你可以随时重构它。
  • 你能添加你第一次尝试的代码吗?基于此,讨论清洁度和效率会容易得多
  • 我不确定您所说的“我不关心这里的重复元素”是什么意思。除此之外,merge 似乎是要走的路,即map2.forEach((k,v)-&gt;map1.merge(k, v, (l1,l2)-&gt;{ l1.addAll(l2); return l1; }));
  • 编辑建议的更改。
  • @Holger 我不关心列表中的重复项,我的意思是。谢谢你的建议顺便说一句。我会试试看。

标签: java collections java-8


【解决方案1】:

希望此代码有所帮助。您应该迭代其中一个列表并添加或更新另一个列表。

public static HashMap<String, ArrayList<Object>> merge(HashMap<String, ArrayList<Object>> list_1, HashMap<String, ArrayList<Object>> list_2) {
    //Iterate second hash map
    Iterator it = list_2.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry) it.next();
        String key = (String) pair.getKey();
        ArrayList<Object> value = (ArrayList<Object>) pair.getValue();
        if(list_1.containsKey(key)){
            //UPDATE
            list_1.replace(key, value); //Replaces the entry for the specified key only if it is currently mapped to some value.
        } else {
            //ADD
            list_1.put(key, value);
        }
    }
    return list_1;
}

【讨论】:

    【解决方案2】:

    这是一种使用 java8 的 Map.merge() 的方法

    //your two input maps
    Map<String, List<String>> input1 = new HashMap<>();
    Map<String, List<String>> input2 = new HashMap<>();
    Map<String, List<String>>[] arrr = new Map[]{input1,input2};
    
    Map<String, List<String>> merged = new HashMap<>();
    for(Map<String, List<String>> input:arrr){
      for(Entry<String, List<String>> e:input.entrySet()){
        merged.merge(e.getKey(), e.getValue(), (v1,v2)->{v1.addAll(v2);return v1;});
      }
    }
    

    这会创建一个 Map 实例作为输出 (merged)。我没有对此进行测试,所以我不确定merge 的内部运作是否会导致v1 在某些时候变为null

    【讨论】:

    • 不想拥有第三张地图,而是将一张与另一张合并。谢谢,会尝试修改这个。
    • 此外,嵌套的 for 循环不会很好。
    • @raghav 由于您有 2 个输入映射,因此外部循环恰好重复了两次。由于这些映射之间的键可能不同,因此您需要将两者合并。那么这不是一个好主意吗?
    • 不质疑您回答的价值。只是我工作场所的人对嵌套循环很敏感。谢谢。
    【解决方案3】:

    如果您从Map&lt;String, ArrayList&gt; 切换到guavaMultimap,您的解决方案将更具可读性

    然后可以使用putAll进行合并

    multimap.putAll(secondMultimap);
    

    【讨论】:

    • putAll() 也可以在 Java 的 Maps 中使用,但是如果键已经存在,putAll() 不会替换值?
    猜你喜欢
    • 1970-01-01
    • 2014-04-26
    • 2021-04-25
    • 2020-03-17
    • 2017-05-19
    • 2019-01-05
    • 2023-03-26
    • 1970-01-01
    • 2018-09-22
    相关资源
    最近更新 更多