Получить доступ

Какое правило связывает equals() и hashCode()?

MiddleРавенство, equals и hashCode
Ещё спрашивают так:
  • Почему при переопределении equals обязательно переопределять и hashCode?
  • Почему в Java при переопределении equals обязательно переопределять и hashCode?
Коротко

Равные по equals объекты обязаны иметь равный hashCode; обратное не требуется — коллизии нормальны. Иначе HashMap и HashSet ищут в другой корзине и не находят равный объект: до вызова equals дело не доходит.

  • Переопределили equals без hashCode — дубликаты в HashSet, «пропавшие» ключи
  • Считать hashCode по тем же полям, что equals: Objects.hash
  • Изменяемые поля в hashCode ключа — объект потеряется после изменения

А ещё Record и Lombok @EqualsAndHashCode генерируют согласованную пару

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

HashMap: put, коллизия и resize

Подробно

Как HashMap ищет ключ: вычисляет hashCode, по нему выбирает корзину, и только внутри неё сравнивает кандидатов через equals.

class Point {
    final int x, y;
    @Override public boolean equals(Object o) {
        return o instanceof Point p && x == p.x && y == p.y;
    }
    // hashCode не переопределён
}
Set<Point> set = new HashSet<>();
set.add(new Point(1, 2));
set.contains(new Point(1, 2));   // скорее всего false

hashCode по умолчанию — от идентичности объекта, у двух равных точек разные хеши → разные корзины → equals не вызывается.

Контракт hashCode:

  • равные по equals — равные hashCode (обязательно);
  • неравные могут совпадать (коллизия), но чем реже — тем быстрее таблица;
  • значение стабильно, пока не меняются поля, участвующие в equals.

Правильно: Objects.hash(x, y) или вручную 31 * x + y; те же поля, что в equals.

Что хотят услышать

  • Контракт в обе стороны.
  • Механика поиска в HashMap и последствия нарушения.
  • Как реализовать.

Частые ошибки

  • Переопределить equals и забыть hashCode.
  • Делать hashCode на основе изменяемого состояния ключа.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Равные по equals объекты обязаны иметь равный hashCode (обратное не требуется — коллизии допустимы)
  • ✗Равный hashCode гарантирует равенство по equals
  • ✗hashCode обязан быть уникален у каждого объекта
  • ✗equals и hashCode независимы друг от друга

Что спросят дальше

  • Как HashMap обрабатывает коллизии?
  • Почему ключи HashMap лучше делать неизменяемыми?
  • Что будет, если hashCode всегда возвращает 0?
  • Как HashMap обрабатывает коллизии и при чём тут treeify?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем