Ответ
Использование изменяемого объекта как ключа — критическая ошибка, ведущая к нарушению работы HashMap/HashSet.
Проблемы:
- Потеря значения: После изменения ключа его
hashCode()меняется, но запись остаётся в старой корзине (bucket). Поиск по новому хэшу ведёт в другую корзину и возвращаетnull. - Нарушение контракта: Ключ должен быть константным относительно
equals()иhashCode()на всё время нахождения в коллекции. - Утечка памяти: Записи со «сломанными» ключами могут оставаться в коллекции, не находясь при поиске.
Демонстрация проблемы:
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 полями) в качестве ключей.