Как в Java определяется равенство ключей в Map (HashMap)?

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

Ответ

В HashMap (и других реализациях Map) равенство ключей определяется строго по контракту методов equals() и hashCode().

Механизм работы:

  1. При добавлении пары put(key, value) вычисляется хэш-код ключа (hashCode()).
  2. По хэш-коду находится соответствующий бакет (корзина).
  3. Внутри бакета ключи сравниваются с помощью метода equals().

Ключи считаются совпадающими, если:

(key1 == key2) || (key1.hashCode() == key2.hashCode() && key1.equals(key2))

На практике это означает, что equals() возвращает true.

Пример с проблемой:

class BadKey {
    String id;
    // НЕТ переопределения equals() и hashCode() -> используется Object.equals()
}

Map<BadKey, String> map = new HashMap<>();
BadKey k1 = new BadKey(); k1.id = "a";
BadKey k2 = new BadKey(); k2.id = "a";

map.put(k1, "value1");
map.put(k2, "value2"); // Разные объекты по equals() -> ДВА разных ключа в map!
System.out.println(map.size()); // Вывод: 2

Best Practice: Для кастомных объектов, используемых как ключи, обязательно корректно переопределять equals() и hashCode(), основываясь на одних и тех же значимых полях. Это гарантирует, что логически одинаковые ключи будут корректно находиться и перезаписываться в Map.