如何组合包含相同类型的两个HashMap对象?

时间:2010-11-28 23:23:29

标签: java hashmap

我有两个HashMap对象定义如下:

HashMap<String, Integer> map1 = new HashMap<String, Integer>();
HashMap<String, Integer> map2 = new HashMap<String, Integer>();

我还有第三个HashMap对象:

HashMap<String, Integer> map3;

如何将map1map2合并到map3

16 个答案:

答案 0 :(得分:306)

map3 = new HashMap<>();

map3.putAll(map1);
map3.putAll(map2);

答案 1 :(得分:93)

如果您知道自己没有重复密钥,或者希望map2中的值覆盖重复密钥map1的值,则可以写

map3 = new HashMap<>(map1);
map3.putAll(map2);

如果您需要更多地控制值的组合方式,可以使用Java 8中添加的Map.merge,它使用用户提供的BiFunction来合并重复键的值。 merge针对各个键和值进行操作,因此您需要使用循环或Map.forEach。这里我们连接重复键的字符串:

map3 = new HashMap<>(map1);
for (Map.Entry<String, String> e : map2.entrySet())
    map3.merge(e.getKey(), e.getValue(), String::concat);
//or instead of the above loop
map2.forEach((k, v) -> map3.merge(k, v, String::concat));

如果您知道自己没有重复的密钥并希望强制执行,则可以使用抛出AssertionError的合并功能:

map2.forEach((k, v) ->
    map3.merge(k, v, (v1, v2) ->
        {throw new AssertionError("duplicate values for key: "+k);}));

从这个特定问题退一步,Java 8流库提供toMapgroupingBy Collectors。如果您在循环中重复合并映射,则可以重构计算以使用流,这既可以使用并行流和并发收集器来阐明代码并实现轻松的并行性。

答案 2 :(得分:41)

使用Java 8 Stream API的单线程序:

map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
       .collect(Collectors.toMap(Entry::getKey, Entry::getValue))

此方法的好处之一是能够传递合并函数,该函数将处理具有相同键的值,例如:

map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
       .collect(Collectors.toMap(Entry::getKey, Entry::getValue, Math::max))

答案 3 :(得分:31)

用于合并两个地图的Java 8替代单行程序:

Director::getInstance()->getScheduler()->performFunctionInCocosThread([]{
    // execute code on main thread
});

与方法参考相同:

defaultMap.forEach((k, v) -> destMap.putIfAbsent(k, v));

或者是第三张地图的原始地图解决方案的代号:

defaultMap.forEach(destMap::putIfAbsent);

这是一种将两个映射合并为快速不可变映射的方法Guava,它可以进行最少的中间复制操作:

Map<String, Integer> map3 = new HashMap<String, Integer>(map2);
map1.forEach(map3::putIfAbsent);

有关两个地图中存在的值需要与映射函数组合的情况,另请参阅Merge two maps with Java 8

答案 4 :(得分:26)

如果您的最终地图不需要可变性,则Guava's ImmutableMapBuilderputAll methodJava's Map interface method形成鲜明对比,可以链接。

使用示例:

Map<String, Integer> mergeMyTwoMaps(Map<String, Integer> map1, Map<String, Integer> map2) {
  return ImmutableMap.<String, Integer>builder()
      .putAll(map1)
      .putAll(map2)
      .build();
}

当然,这个方法可以更通用,使用varargs并从参数等循环到putAll Maps但是我想展示一个概念。

此外,ImmutableMap及其Builder几乎没有限制(或可能是功能?):

  • 它们是空的敌对(抛出NullPointerException - 如果map中的任何键或值为null)
  • 构建器不接受重复的密钥(如果添加了重复的密钥则抛出IllegalArgumentException。)

答案 5 :(得分:25)

答案 6 :(得分:17)

您可以将Collection.addAll()用于其他类型,例如ListSet等。对于Map,您可以使用putAll

答案 7 :(得分:11)

用于组合两个可能共享公钥的地图的通用解决方案:

在就地:

public static <K, V> void mergeInPlace(Map<K, V> map1, Map<K, V> map2,
        BinaryOperator<V> combiner) {
    map2.forEach((k, v) -> map1.merge(k, v, combiner::apply));
}

返回新地图:

public static <K, V> Map<K, V> merge(Map<K, V> map1, Map<K, V> map2,
        BinaryOperator<V> combiner) {
    Map<K, V> map3 = new HashMap<>(map1);
    map2.forEach((k, v) -> map3.merge(k, v, combiner::apply));
    return map3;
}

答案 8 :(得分:1)

我经常使用的一小段代码从其他地图创建地图:

static public <K, V> Map<K, V> merge(Map<K, V>... args) {
    final Map<K, V> buffer = new HashMap<>();

    for (Map m : args) {
        buffer.putAll(m);
    }

    return buffer;
}

答案 9 :(得分:1)

您可以使用HashMap<String, List<Integer>>合并两个哈希图,并避免丢失与同一键配对的元素。

HashMap<String, Integer> map1 = new HashMap<>();
HashMap<String, Integer> map2 = new HashMap<>();
map1.put("key1", 1);
map1.put("key2", 2);
map1.put("key3", 3);
map2.put("key1", 4);
map2.put("key2", 5);
map2.put("key3", 6);
HashMap<String, List<Integer>> map3 = new HashMap<>();
map1.forEach((str, num) -> map3.put(str, new ArrayList<>(Arrays.asList(num))));
//checking for each key if its already in the map, and if so, you just add the integer to the list paired with this key
for (Map.Entry<String, Integer> entry : map2.entrySet()) {
    Integer value = entry.getValue();
    String key = entry.getKey();
    if (map3.containsKey(key)) {
        map3.get(key).add(value);
    } else {
        map3.put(key, new ArrayList<>(Arrays.asList(value)));
    }
}
map3.forEach((str, list) -> System.out.println("{" + str + ": " + list + "}"));

输出:

{key1: [1, 4]}
{key2: [2, 5]}
{key3: [3, 6]}

答案 10 :(得分:1)

很晚了,但是让我分享我遇到同样问题时的工作。

Map<String, List<String>> map1 = new HashMap<>();
map1.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map1.put("NZ", Arrays.asList("P1","P2","P3"));

Map<String, List<String>> map2 = new HashMap<>();
map2.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map2.put("NZ", Arrays.asList("P1","P2","P4"));

Map<String, List<String>> collect4 = Stream.of(map1, map2)
                .flatMap(map -> map.entrySet().stream())
                .collect(
                        Collectors.toMap(
                                Map.Entry::getKey,
                                Map.Entry::getValue,
                                (strings, strings2) -> {
                                    List<String> newList = new ArrayList<>();
                                    newList.addAll(strings);
                                    newList.addAll(strings2);
                                    return newList;
                                }
                        )
                );
collect4.forEach((s, strings) -> System.out.println(s+"->"+strings));

它给出以下输出

NZ->[P1, P2, P3, P1, P2, P4]
India->[Virat, Mahi, Rohit, Virat, Mahi, Rohit]

答案 11 :(得分:0)

    HashMap<Integer,String> hs1 = new HashMap<>();
    hs1.put(1,"ram");
    hs1.put(2,"sita");
    hs1.put(3,"laxman");
    hs1.put(4,"hanuman");
    hs1.put(5,"geeta");

    HashMap<Integer,String> hs2 = new HashMap<>();
    hs2.put(5,"rat");
    hs2.put(6,"lion");
    hs2.put(7,"tiger");
    hs2.put(8,"fish");
    hs2.put(9,"hen");

    HashMap<Integer,String> hs3 = new HashMap<>();//Map is which we add

    hs3.putAll(hs1);
    hs3.putAll(hs2);

    System.out.println(" hs1 : " + hs1);
    System.out.println(" hs2 : " + hs2);
    System.out.println(" hs3 : " + hs3);

不会添加重复项(即重复键),因为当我们打印hs3时,键5只会得到一个值,这是最后添加的值,并且会被分配。 ** [Set具有不允许重复的键,但值可以重复的属性]

答案 12 :(得分:0)

方法1:将地图放入列表中,然后加入

 // database is not existing
    console.log('open database and create table');
    db = new sqlite3.Database('./event.db',() => {
      db.run('CREATE TABLE logTable(logfile TEXT,logdate TEXT,referto TEXT, area TEXT,status TEXT,action TEXT)',() => {
      ...
      });

// if db is existing
  db = new sqlite3.Database('./event.db'() => {
    ...
});

方法2:法线贴图合并

public class Test15 {
public static void main(String[] args) {

    Map<String, List<String>> map1 = new HashMap<>();
    map1.put("London", Arrays.asList("A", "B", "C"));
    map1.put("Wales", Arrays.asList("P1", "P2", "P3"));

    Map<String, List<String>> map2 = new HashMap<>();
    map2.put("Calcutta", Arrays.asList("Protijayi", "Gina", "Gini"));
    map2.put("London", Arrays.asList( "P4", "P5", "P6"));
    map2.put("Wales", Arrays.asList( "P111", "P5555", "P677666"));

    System.out.println(map1);System.out.println(map2);



    // put the maps in an ArrayList

    List<Map<String, List<String>>> maplist = new ArrayList<Map<String,List<String>>>();
    maplist.add(map1);
    maplist.add(map2);
    /*
<T,K,U> Collector<T,?,Map<K,U>> toMap(

                                  Function<? super T,? extends K> keyMapper,

                                  Function<? super T,? extends U> valueMapper,

                                  BinaryOperator<U> mergeFunction)
    */

 Map<String, List<String>> collect = maplist.stream()
    .flatMap(ch -> ch.entrySet().stream())
    .collect(
            Collectors.toMap(

            //keyMapper,

            Entry::getKey,

            //valueMapper
            Entry::getValue,

            // mergeFunction
     (list_a,list_b) -> Stream.concat(list_a.stream(), list_b.stream()).collect(Collectors.toList())

            ));



    System.out.println("Final Result(Map after join) => " + collect);
    /*
    {Wales=[P1, P2, P3], London=[A, B, C]}
{Calcutta=[Protijayi, Gina, Gini], Wales=[P111, P5555, P677666], London=[P4, P5, P6]}
Final Result(Map after join) => {Calcutta=[Protijayi, Gina, Gini], Wales=[P1, P2, P3, P111, P5555, P677666], London=[A, B, C, P4, P5, P6]}
*/

}//main


}

答案 13 :(得分:0)

您可以按照下面的代码中的说明使用Map的putAll函数

HashMap<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("a", 1);
map1.put("b", 2);
map1.put("c", 3);
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
map1.put("aa", 11);
map1.put("bb", 12);
HashMap<String, Integer> map3 = new HashMap<String, Integer>();
map3.putAll(map1);
map3.putAll(map2);
map3.keySet().stream().forEach(System.out::println);
map3.values().stream().forEach(System.out::println);

答案 14 :(得分:0)

以下摘录中包含多张地图并将其合并。

=QUERY(QUERY('BI_Keywords Raw Data'!$A:$C, "Select * WHERE B = ' "&B2&" ' " ), "SELECT * OFFSET 1", 0)

演示示例link.

答案 15 :(得分:-1)

你可以使用 - addAll方法

http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html

但总有这个问题 - 如果你的两个哈希映射有任何密钥相同 - 那么它将使用第二个哈希映射中的密钥值覆盖第一个哈希映射中的密钥值。

为了更安全 - 更改键值 - 您可以在键上使用前缀或后缀 - (第一个哈希映射的不同前缀/后缀和第二个哈希映射的不同前缀/后缀)