Ответ
Ключ может стать "потерянным" в Map после изменения, что приведет к непредсказуемому поведению.
Проблема: HashMap использует хэш-код ключа для определения бакета. Если ключ изменяется после добавления, его хэш-код может измениться, но запись останется в старом бакете.
Пример:
class MutableKey {
private String value;
public MutableKey(String value) { this.value = value; }
public void setValue(String value) { this.value = value; }
@Override
public int hashCode() { return value.hashCode(); }
@Override
public boolean equals(Object o) { /* реализация */ }
}
Map<MutableKey, String> map = new HashMap<>();
MutableKey key = new MutableKey("initial");
map.put(key, "value");
// Изменяем ключ - НАРУШАЕМ КОНТРАКТ!
key.setValue("modified");
// Проблемы:
System.out.println(map.get(key)); // null - запись не найдена
System.out.println(map.containsKey(key)); // false
// Но запись все еще существует в map!
map.forEach((k, v) -> System.out.println(v)); // Выведет "value"
Последствия:
- Потеря доступа к значению через измененный ключ
- Утечка памяти - запись остается в map, но недоступна
- Нарушение контракта Map (ключи должны быть immutable)
Решение:
- Используйте неизменяемые ключи (String, Integer, LocalDate)
- Если ключ должен меняться - удалите старую запись и добавьте новую
- Для кастомных ключей:
- Сделайте поля
final - Переопределите
equals()иhashCode()на основе final-полей - Реализуйте
Comparableдля TreeMap
- Сделайте поля