Ответ
Методы hashCode() и equals() работают в паре для обеспечения корректной работы объектов в хеш-ориентированных коллекциях, таких как HashMap, HashSet и Hashtable. Нарушение контракта между ними приводит к трудноуловимым ошибкам.
Основной контракт (согласно JavaDoc Object):
- Если два объекта равны согласно
equals(Object), то ихhashCode()должны возвращать одинаковое целочисленное значение. - Обратное необязательно: разные объекты (по
equals) могут иметь одинаковый хеш-код (коллизия). Это нормально, но снижает производительность.
Что происходит при нарушении контракта?
Объект, помещённый в HashMap, может быть не найден при поиске по эквивалентному ключу, так как коллекция сначала ищет корзину по hashCode(), и только затем сравнивает ключи внутри корзины через equals().
Пример корректной реализации:
public class User {
private final Long id;
private final String email;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id); // Сравниваем только по id
}
@Override
public int hashCode() {
return Objects.hash(id); // Используем те же поля, что и в equals()
}
}
Использование Objects.hash() и Objects.equals() упрощает соблюдение контракта.