# How to merge two maps in Java

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Jul 17, 2021. Topics: Java.
Canonical URL: https://attacomsian.com/blog/java-merge-maps

> Learn how to merge or join two maps into one using java 8 Streams API and the Map.putAll() method.

There are multiple ways to merge or join two instances of the `HashMap` class in Java. In this article, you'll learn to join maps with and without handling duplicate keys.

Let us say you have got the following two `HashMap` objects that you want to combine:

```java
Map<String, Integer> map1 = new HashMap<>();
map1.put("A", 1);
map1.put("B", 2);
map1.put("C", 3);
map1.put("F", 4);

Map<String, Integer> map2 = new HashMap<>();
map2.put("A", 3);
map2.put("B", 4);
map2.put("D", 5);
```

## `Map.putAll()` Method

The `Map.putAll()` method provides a quick and simple solution to merge two maps. This method copies all key-value pairs from the second map to the first map.

Since a `HashMap` object can not store duplicate keys, the `Map.putAll()` method override the value of duplicate keys in the first map with values from the second map.

```java
// Merge second map with first map
map1.putAll(map2);

// Print new map
System.out.println(map1);
```

Here is the output:

```bash
{A=3, B=4, C=3, D=5, F=4}
```

## `Map.merge()` Method

The `Map.merge()` method was introduced in Java 8 and is useful for joining maps with duplicate keys.  

This method takes three arguments as input: key, value, and a remapping function to merge values for duplicate keys.

If the specified key is not already associated with a value or is associated with `null`, the `Map.merge()` method associates it with the given non-null value.

Otherwise, the `Map.merge()` method replaces the value with the results of the given remapping function. If the result of the remapping function is `null`, it removes the key altogether.

The following example demonstrates how you can combine the values of duplicate keys using the remapping function of `Map.merge()`:

```java
// Merge second map with first map
map2.forEach((key, value) ->
        map1.merge(key, value, (v1, v2) -> v1 + v2) );

// Print new map
System.out.println(map1);

// {A=4, B=6, C=3, D=5, F=4}
```

Notice the values of key `B`. It had value 2 in `map1` and value 4 in `map2`. After the merge, it has a combined value of 6 in the merged map. The remapping function allows you to write any merge logic that suits your needs. 

## `Stream.concat()` Method

The `Stream.concat()` method from the Stream API in Java 8 can also be used to combine two maps.

As the name suggests, the `Stream.concat()` method combines the `Map` instances into one `Stream` object:

```java
Stream<Map.Entry<String, Integer>> combined = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream());
```

Now, we can use the `Collectors.toMap()` method to collect the result into a new `Map` instance:

```java
Map<String, Integer> merged = combined.collect(
        Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
```

The above solution works fine as long as there are no duplicate keys. If it encounters any duplicate entry, it will throw an `IllegalStateException` exception.

To handle duplicate entries, you can pass a merger function as a third parameter to the collector:

```javascript
Map<String, Integer> merged = combined.collect(
        Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue,
                (v1, v2) -> v1 + v2));

// Print new map
System.out.println(merged);

// {A=4, B=6, C=3, D=5, F=4}
```

## `Stream.of()` Method

`Stream.of()` is another method from the Stream API that can be used to merge two maps in Java 9 and above:

```java
// Merge the second map with the first map
Map<String, Integer> merged = Stream.of(map1, map2)
        .flatMap(map -> map.entrySet().stream())
        .collect(Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue,
                (v1, v2) -> v1 + v2));

// Print new map
System.out.println(merged);

// {A=4, B=6, C=3, D=5, F=4}
```

In the above example, we first transform `map1` and `map2` into a unified stream with the help of `Stream.of()` and `Stream.flatMap()` methods. Next, we convert the stream into a map using a collector function.
