Как объединить две Map
Короткий ответ
putAll() копирует все пары из второй Map. При совпадении ключей побеждает значение из второй:
void main() {
var defaults = new TreeMap<>(Map.of("theme", "light", "lang", "en"));
var user = Map.of("theme", "dark");
defaults.putAll(user);
IO.println(defaults);
}Результат:
{lang=en, theme=dark}Сложить значения
merge() объединяет значения по правилу — например, складывает количества:
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);
}Результат:
{cake=1, coffee=4, tea=5}Через поток
Поток подходит, когда Map несколько:
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);
}Результат:
{a=3, b=6}Частая ошибка
Вызвать putAll() у Map.of(). Такая Map неизменяемая:
void main() {
var settings = Map.of("lang", "en");
settings.putAll(Map.of("theme", "dark"));
}Результат:
Exception in thread "main" java.lang.UnsupportedOperationExceptionНачинайте с изменяемой копии: new HashMap<>(settings).
Функции из этого ответа
- Map.put() — Записывает значение по ключу, заменяя прежнее.
- Map.merge() — Добавляет значение по ключу или объединяет его с уже существующим.
- Collectors.toMap() — Сборщик, который строит словарь из элементов потока.