Ответ вслух Middle ООП и класс Object спрашивают часто обновлено

equals и hashCode: зачем и как

Вопрос

Зачем переопределять equals и hashCode вместе? Что сломается, если нарушить контракт, и как правильно их писать?

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

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

HashMap и HashSet сначала по hashCode выбирают корзину, а внутри неё сравнивают equals. Отсюда контракт: если объекты равны по equals, хеши обязаны совпадать.

Что должно прозвучать в ответе

  • Контракт: равные по equals имеют равный hashCode

  • Хеш-коллекции ищут корзину по hashCode, затем сравнивают equals

  • Без hashCode равный объект не находится в HashMap/HashSet

  • Поля из hashCode не должны меняться, пока объект в коллекции

  • Использовать одни и те же поля в обоих методах, Objects.hash/Objects.equals

  • Для значений record генерирует оба метода

Что могут спросить следом

  • Что будет, если hashCode всегда возвращает 1?
  • instanceof или getClass в equals: что выбрать?
  • Как equals работает у JPA-сущностей с генерируемым id?

Разбор

HashMap и HashSet сначала по hashCode выбирают корзину, а внутри неё сравнивают equals. Отсюда контракт: если объекты равны по equals, хеши обязаны совпадать. Если переопределить только equals, два логически равных объекта попадут в разные корзины, и contains вернёт false. Пишу оба метода по одному и тому же набору полей: Objects.equals для полей и Objects.hash для хеша, сигнатура строго equals(Object) с @Override. Поля, участвующие в хеше, не должны меняться, пока объект лежит в коллекции, иначе он потеряется. Если hashCode вернёт константу, всё будет работать, но поиск выродится в линейный. Для классов-значений сейчас просто беру record.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.