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

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

我还有第三个HashMap对象:

HashMap<String, Integer> map3;

如何将map1和map2合并为map3?


当前回答

方法1:将映射放在List中,然后连接

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


}

方法二:法线映射合并

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);
    
    
    

    /*
<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 = Stream.of(map1,map2)
    .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


}
    

在Python中,HashMap被称为字典,我们可以很容易地合并它们。

x = {'Roopa': 1, 'Tabu': 2}
y = {'Roopi': 3, 'Soudipta': 4}


z = {**x,**y}
print(z)
{'Roopa': 1, 'Tabu': 2, 'Roopi': 3, 'Soudipta': 4}

其他回答

如果知道没有重复的键,或者希望map2中的值覆盖map1中的值以获得重复的键,那么可以只写

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

如果需要更多地控制值的组合方式,可以使用Map。merge,在Java 8中添加,它使用用户提供的biffunction来合并重复键的值。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));

如果你知道你没有重复的键,并且想要强制它,你可以使用merge函数抛出AssertionError:

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

从这个特定的问题后退一步,Java 8流库提供了toMap和groupingBy collector。如果在循环中重复合并映射,则可以重新构造计算以使用流,这既可以澄清代码,又可以使用并行流和并发收集器轻松实现并行。

用于合并两个映射的Java 8替代一行程序:

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

方法参考也一样:

defaultMap.forEach(destMap::putIfAbsent);

或原始地图解与第三个地图的幂分量:

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

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

ImmutableMap.Builder<String, Integer> builder = ImmutableMap.<String, Integer>builder();
builder.putAll(map1);
map2.forEach((k, v) -> {if (!map1.containsKey(k)) builder.put(k, v);});
ImmutableMap<String, Integer> map3 = builder.build();

请参见使用Java 8合并两个映射,了解需要使用映射函数组合两个映射中的值的情况。

map3 = new HashMap<>();

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

假设输入如下:

    import java.util.stream.Stream;
    import java.util.stream.Collectors;
    import java.util.Map;
   
    ...

    var m1 = Map.of("k1", 1, "k2", 2);
    var m2 = Map.of("k3", 3, "k4", 4);

当你确定两个输入映射之间没有任何键冲突时,一个避免任何突变并产生不可变结果的简单表达式可以是:

    var merged = Stream.concat(
        m1.entrySet().stream(),
        m2.entrySet().stream()
    ).collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));

在可能发生键冲突的情况下,我们可以提供一个lambda来指定如何去重复它们。例如,如果我们想保留最大的值,以防两个输入中都有一个条目,我们可以:

    .collect(Collectors.toUnmodifiableMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        Math::max))  // any function  (Integer, Integer) -> Integer  is ok here

你可以使用HashMap<String, List<Integer>>来合并两个HashMap,避免丢失与相同键配对的元素。

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]}