Как накапливать значения по ключу через Map.merge в Java

Как накапливать значения по ключу через Map.merge в Java
Содержание статьи

Для накопления количества по коду товара можно использовать Map.merge. Метод добавит первое значение или объединит его с уже сохранённым. На Mentoring.digital разберём обычную изменяемую HashMap и случаи, в которых результат может оказаться неожиданным.

Суммируем количество по товару

import java.util.HashMap;
import java.util.Map;

Map<String, Integer> quantities = new HashMap<>();
quantities.merge("book", 2, Integer::sum);
quantities.merge("book", 3, Integer::sum);
quantities.merge("pen", 1, Integer::sum);

System.out.println(quantities.get("book")); // 5
System.out.println(quantities.get("pen"));  // 1

Первый аргумент задаёт ключ, второй содержит входящее значение, третий описывает объединение. Если ненулевое старое значение существует, функция получает сначала его, затем входящее значение. В примере Integer::sum складывает два количества.

Если ключа нет, входящее значение сохраняется без вызова функции. Поэтому функция объединения не подходит для действия, которое обязательно должно выполняться при каждом обращении.

Различаем три случая с null

quantities.put("book", null);
quantities.merge("book", 4, Integer::sum);
System.out.println(quantities.get("book")); // 4

quantities.merge("book", 1, (oldValue, incoming) -> null);
System.out.println(quantities.containsKey("book")); // false

Старое null обрабатывается как отсутствие ненулевого значения: сохраняется переданное число 4. Возврат null из функции объединения означает удаление существующей записи. Это не сохранение записи со значением null.

Сам входящий аргумент value у merge должен быть ненулевым. Передать null вместо числа для обозначения отсутствующих данных нельзя. Сначала определите отдельное правило обработки такого входа.

Учитываем изменяемость и параллельную работу

Метод меняет карту. Карта, запрещающая изменение, может отклонить операцию. Внутри функции объединения не следует менять ту же карту: возвращайте рассчитанный результат.

Использование merge не делает HashMap безопасной для одновременных изменений из нескольких потоков. Для такой задачи выбирают подходящую реализацию и изучают именно её гарантии. Кроме того, обычное сложение Integer не защищает счётчик от переполнения.

Что проверить в своей задаче

Возьмите новый ключ, повторный ключ и ключ со старым null. Добавьте правило удаления и проверьте наличие записи через containsKey. Затем объясните, допустимо ли удаление в вашей предметной области или такой результат должен считаться ошибкой.

Практику коллекций можно отработать на курсах Java с наставником. Подходящую структуру и правила накопления значений разберите с ментором по Java.

Похожие статьи по данной теме