Мутабельный объект как ключ HashMap — рабочий код до первой мутации
Класс без иммутабельности используют как ключ HashMap, кладут объект, потом меняют поле, участвующее в hashCode() — и get() с тем же ключом возвращает null, хотя объект физически лежит в мапе.
Причина в том, что hash вычисляется в момент put() и определяет, в каком bucket окажется запись. Если после этого изменить поле, влияющее на hashCode(), get() пересчитает hash по текущему состоянию объекта и пойдёт искать в другом bucket — не найдёт, хотя entrySet() покажет запись на месте.
class Point { private int x; private int y;
// сеттеры, equals/hashCode по x и y }
Map map = new HashMap<>(); Point p = new Point(1, 2); map.put(p, "start");
p.setX(5); map.get(p); // null
Спросят: почему size() покажет 1, а get вернёт null? Потому что структура хранит запись в bucket по старому hash, а get пересчитывает hash по текущему состоянию объекта и идёт в другой bucket.
Правило простое: ключи HashMap должны быть иммутабельны, либо equals/hashCode не должны зависеть от изменяемых полей.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки
· 15.08
на собесе это красиво звучит, но в проде я давно просто беру record (java 16+) для составных ключей — иммутабельность из коробки, ни сеттеров, ни соблазна мутировать. а если ключ по сути пара строк или чисел, склеиваю в один string и вообще не думаю про bucket-логику
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
коммент удалён