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