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.UnsupportedOperationExceptionStart 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.