Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to merge two maps

Short answer

putAll() copies every pair from the second Map. When keys collide, the value from the second one wins:

void main() {
    var defaults = new TreeMap<>(Map.of("theme", "light", "lang", "en"));
    var user = Map.of("theme", "dark");
 
    defaults.putAll(user);
    IO.println(defaults);
}

Output:

{lang=en, theme=dark}

Adding values up

merge() combines values with a rule — for example, adds up quantities:

void main() {
    var monday = Map.of("tea", 3, "cake", 1);
    var tuesday = Map.of("tea", 2, "coffee", 4);
 
    var total = new TreeMap<>(monday);
    tuesday.forEach((item, count) -> total.merge(item, count, Integer::sum));
    IO.println(total);
}

Output:

{cake=1, coffee=4, tea=5}

With a stream

A stream works well when there are several Maps:

void main() {
    var parts = List.of(Map.of("a", 1), Map.of("a", 2, "b", 5), Map.of("b", 1));
 
    var total = parts.stream()
            .flatMap(map -> map.entrySet().stream())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum, TreeMap::new));
    IO.println(total);
}

Output:

{a=3, b=6}

Common mistake

Calling putAll() on a Map.of(). Such a map is unmodifiable:

void main() {
    var settings = Map.of("lang", "en");
    settings.putAll(Map.of("theme", "dark"));
}

Output:

Exception in thread "main" java.lang.UnsupportedOperationException

Start with a modifiable copy: new HashMap<>(settings).

Functions used in this recipe

  • Map.put() — Stores a value under a key, replacing the old one.
  • Map.merge() — Adds a value under a key or combines it with the existing one.
  • Collectors.toMap() — A collector that builds a map from stream elements.

Thanks for reading!

Donate to the site — we work hard for you.