Что происходит в Java при добавлении значения по уже существующему ключу в Map?

«Что происходит в Java при добавлении значения по уже существующему ключу в Map?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

При добавлении пары ключ-значение в Map (например, HashMap) с ключом, который уже присутствует в коллекции, старое значение, ассоциированное с этим ключом, перезаписывается новым значением. Ключ остается прежним. Это фундаментальное свойство Map — каждый ключ может быть связан только с одним значением.

Базовое поведение (перезапись):

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 10); // Добавляет пару ("Alice", 10)
scores.put("Alice", 25); // Перезаписывает значение. Теперь ("Alice", 25)

System.out.println(scores.get("Alice")); // Вывод: 25
System.out.println(scores.size()); // Вывод: 1 (ключ один)

Методы для "складывания" значений (если это требуется): Если по бизнес-логике нужно не перезаписать, а, например, сложить числовые значения, следует использовать специальные методы:

  1. merge() — Идеален для агрегации:

    Map<String, Integer> totals = new HashMap<>();
    totals.put("budget", 1000);
    
    // Если ключ "budget" существует, сложить старое и новое значение.
    // Если ключа нет, просто положить значение 500.
    totals.merge("budget", 500, Integer::sum); // Теперь "budget" = 1500
    totals.merge("newItem", 300, Integer::sum); // Ключа не было -> "newItem" = 300
  2. compute() — Полный контроль над вычислением нового значения:

    Map<String, List<String>> groups = new HashMap<>();
    
    groups.compute("teamA", (key, currentList) -> {
        if (currentList == null) {
            currentList = new ArrayList<>();
        }
        currentList.add("New Member");
        return currentList;
    });
  3. computeIfAbsent() / computeIfPresent() — Упрощенные версии для частых сценариев.

Важно: Стандартный put() всегда выполняет замену, а не сложение. Для агрегирующих операций необходимо явно использовать merge(), compute() или вручную получать старое значение.