К чему приведёт использование изменяемого (mutable) объекта в качестве ключа в HashMap?

«К чему приведёт использование изменяемого (mutable) объекта в качестве ключа в HashMap?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Использование изменяемого объекта как ключа — критическая ошибка, ведущая к нарушению работы HashMap/HashSet.

Проблемы:

  1. Потеря значения: После изменения ключа его hashCode() меняется, но запись остаётся в старой корзине (bucket). Поиск по новому хэшу ведёт в другую корзину и возвращает null.
  2. Нарушение контракта: Ключ должен быть константным относительно equals() и hashCode() на всё время нахождения в коллекции.
  3. Утечка памяти: Записи со «сломанными» ключами могут оставаться в коллекции, не находясь при поиске.

Демонстрация проблемы:

class MutableKey {
    private int id;
    // конструктор, геттеры, сеттеры...
    public void setId(int id) { this.id = id; }
    @Override public int hashCode() { return id; }
}

Map<MutableKey, String> map = new HashMap<>();
MutableKey key = new MutableKey(1);
map.put(key, "value");

key.setId(2); // Меняем поле, влияющее на hashCode()
System.out.println(map.get(key)); // null — значение потеряно!

Решение: Используйте только иммутабельные объекты (String, Integer, собственные классы с final полями) в качестве ключей.