Мутабельный объект как ключ 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 — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки