


Чтобы собрать элементы по ключу, часто нужен список внутри Map. computeIfAbsent получает существующее непустое значение или вычисляет новое, если ключ отсутствует либо связан с null. В примере Mentoring.digital будем добавлять имена в группу без отдельного блока проверки.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Map<String, List<String>> groups = new HashMap<>();
groups.computeIfAbsent("backend", key -> new ArrayList<>())
.add("Ada");
groups.computeIfAbsent("backend", key -> new ArrayList<>())
.add("Lin");
System.out.println(groups.get("backend")); // [Ada, Lin]
В первый раз функция создаёт ArrayList и помещает его в карту. Во второй раз в карте уже есть список, поэтому возвращается он же. Метод add вызывается на полученном списке, а не на Map.
Фрагмент предназначен для тела метода или интерактивного окружения Java. В обычном файле приложения добавьте класс и main, а импорты оставьте перед объявлением класса. Здесь рассматривается последовательное выполнение в одном потоке.
Если карта разрешает null и ключ связан с ним, computeIfAbsent тоже попытается вычислить значение. Когда сама функция вернула null, новое значение в карту не добавляется. Поэтому последующий вызов может снова запустить вычисление.
Map<String, String> names = new HashMap<>();
String value = names.computeIfAbsent("missing", key -> null);
System.out.println(value); // null
System.out.println(names.containsKey("missing")); // false
Не вызывайте метод результата без проверки, если функция действительно может вернуть null. В примере со списком конструктор возвращает список, поэтому этой неопределённости нет. Но при загрузке данных из внешнего источника условие может отличаться.
В putIfAbsent передаётся уже вычисленное значение. Выражение, которое его создаёт, будет вычислено до самого вызова метода. В computeIfAbsent передаётся функция: она нужна только при отсутствии непустого значения.
Не меняйте эту же карту внутри функции вычисления. И не приписывайте обычному HashMap потокобезопасность из-за названия метода. Гарантии атомарности зависят от конкретной реализации Map; совместное изменение вложенного ArrayList тоже требует отдельного решения.
Практическое задание: сгруппируйте три заявки по status. Проверьте повторный статус, новый статус и пустой входной список. Затем объясните, почему замена HashMap на ConcurrentHashMap сама по себе не делает ArrayList безопасным для одновременных add.
Коллекции и работу с функциями можно изучать на курсе Java с наставником. Для разбора конкретной модели данных подойдёт ментор по Java.