How can I combine two HashMap objects containing the same types?
我有两个
1 2 |
我还有第三个
1 |
如何将
1 2 3 4 | map3 = new HashMap<>(); map3.putAll(map1); map3.putAll(map2); |
如果您知道没有重复键,或者您希望
1 2 | map3 = new HashMap<>(map1); map3.putAll(map2); |
如果需要更多地控制值的组合方式,可以使用在Java 8中添加的
1 2 3 4 5 |
如果您知道没有重复的密钥并且想要强制执行它,则可以使用抛出
1 2 3 | map2.forEach((k, v) -> map3.merge(k, v, (v1, v2) -> {throw new AssertionError("duplicate values for key:"+k);})); |
从这个特定问题退一步,Java 8流库提供了
使用Java 8 Stream API的单线程:
1 2 | map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Entry::getKey, Entry::getValue)) |
此方法的好处之一是能够传递合并函数,该函数将处理具有相同键的值,例如:
1 2 | map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Entry::getKey, Entry::getValue, Math::max)) |
用于合并两个映射的Java 8替代单行程序:
1 | defaultMap.forEach((k, v) -> destMap.putIfAbsent(k, v)); |
与方法参考相同:
1 | defaultMap.forEach(destMap::putIfAbsent); |
或者使用第三张地图的原始地图解决方案的idemponent:
这里有一种方法可以将两个映射合并到具有最少可能的中间复制操作的Guava的快速不可变映射中:
1 2 3 4 |
有关两个映射中存在的值需要与映射函数组合的情况,另请参阅使用Java 8合并两个映射。
如果您的最终地图不需要可变性,那么Guava的
使用示例:
1 2 3 4 5 6 |
当然,这个方法可以更通用,使用varargs并从参数等循环到
此外,
-
它们是空的敌对(throw
NullPointerException - 如果map中的任何键或值为null) -
Builder不接受重复键(如果添加了重复键,则抛出
IllegalArgumentException )。
HashMap有一个
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
您可以将Collection.addAll()用于其他类型,例如
用于组合两个可能共享公共密钥的映射的通用解决方案:
到位:
1 2 3 4 | 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)); } |
返回新地图:
1 2 3 4 5 6 | 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; } |
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 +"}")); |
输出:
1 2 3 | {key1: [1, 4]} {key2: [2, 5]} {key3: [3, 6]} |
我经常使用一个小片段来创建其他地图的地图:
1 2 3 4 5 6 7 8 9 | 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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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具有不允许重复键的属性,但值可以重复]
你可以使用--addAll方法
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
但是总有这个问题 - 如果你的两个哈希映射具有相同的任何键 - 那么它将使用第二个哈希映射中的键值覆盖第一个哈希映射中的键值。
为了更安全 - 更改键值 - 您可以在键上使用前缀或后缀 - (第一个哈希映射的不同前缀/后缀和第二个哈希映射的不同前缀/后缀)