Требуется ли неизменяемый ключ для HashMap при работе в одном потоке?

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

Ответ

Нет, техническое требование отсутствует, но это критически важная рекомендация.

В однопоточном приложении HashMap не сломается от использования изменяемого ключа, но это приведет к логическим ошибкам и потере данных.

Проблема: HashMap находит значение по хэш-коду ключа и проверке равенства (equals). Если после помещения пары ключ-значение в мапу изменить состояние ключа так, что изменится его hashCode() или результат equals(), то исходное значение станет недостижимым.

Пример:

class MutableKey {
    private String value;
    // конструктор, геттеры, сеттеры, hashCode, equals
}

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

// Изменяем ключ
key.setValue("changed");

// Попытка найти значение -> вернется null
System.out.println(map.get(key)); // null
// При этом значение "MyValue" осталось в мапе, но "потерялось".

Практические правила:

  1. Всегда используйте неизменяемые типы для ключей (String, Integer, собственные record или классы с final полями).
  2. Если объект ключа должен быть изменяемым, никогда не модифицируйте его после использования в качестве ключа в HashMap или любом другом хэш-базированном коллекторе.