Ответ
При реализации equals() необходимо соблюдать его контракт:
- Рефлексивность:
x.equals(x)→true. - Симметричность:
x.equals(y)→trueтогда и только тогда, когдаy.equals(x)→true. - Транзитивность: Если
x.equals(y)иy.equals(z), тоx.equals(z). - Согласованность: Многократные вызовы возвращают одинаковый результат, если объекты не изменялись.
- Сравнение с null:
x.equals(null)→false.
Обязательно переопределяйте hashCode(), чтобы объекты, признанные равными по equals(), имели одинаковый хеш-код. Это критично для корректной работы HashMap, HashSet.
Шаблон реализации с использованием java.util.Objects:
@Override
public boolean equals(Object o) {
// 1. Проверка ссылки
if (this == o) return true;
// 2. Проверка типа и null
if (o == null || getClass() != o.getClass()) return false;
// 3. Приведение типа и сравнение полей
MyClass other = (MyClass) o;
return Objects.equals(this.field1, other.field1) &&
Objects.equals(this.field2, other.field2) &&
this.field3 == other.field3; // для примитивов
}
@Override
public int hashCode() {
// Генерация хеш-кода на основе тех же полей, что и в equals()
return Objects.hash(field1, field2, field3);
}
Важные моменты:
- Используйте
Objects.equals()для безопасного сравнения ссылок (включаяnull). - Для примитивных типов используйте
==. - Сначала сравнивайте наиболее «дешевые» или чаще различающиеся поля.
- Рассмотрите возможность использования автоматической генерации через IDE или Lombok (
@EqualsAndHashCode).
Ответ 18+ 🔞
Давай разберём эту тему, а то некоторые пишут equals() так, что потом сами от себя охуевают, когда HashMap начинает вести себя как пизда с ушами.
Слушай, контракт equals() — это не просто бумажка, это, блядь, священный договор с виртуальной машиной. Нарушишь — получишь неопределённое поведение, и будешь потом неделю дебажить, почему у тебя в HashSet дубликаты плодятся.
Вот эти пять пунктов — это как пять заповедей, ёпта. Особенно про симметричность. Классика жанра: пишешь ты класс Employee, наследуешься от Person, переопределяешь equals() только в Employee. Потом сравниваешь employee.equals(person) — false, а person.equals(employee) — true. И всё, пиздец, симметричность нарушена, коллекции ебут мозг.
А теперь главное, на чём все обламываются: hashCode() и equals() — это неразлучная парочка, как хуй с яйцами. Если переопределил один — обязан переопределить и второй, и так, чтобы для равных объектов хеш-коды были одинаковые. Иначе твой объект в HashMap просто потеряется, как хуй в стоге сена. Объекты равны, а хеши разные — ищи-свищи свою запись, её там нет.
Шаблон-то, в принципе, норм, но давай я его на пальцах объясню:
@Override
public boolean equals(Object o) {
// 1. Это же я? Если да — сразу true, нехуй мозги парить.
if (this == o) return true;
// 2. Это null или объект другого класса? Если да — false, и не спорь.
if (o == null || getClass() != o.getClass()) return false;
// 3. Теперь кастуем и сравниваем поля.
MyClass other = (MyClass) o;
return Objects.equals(this.name, other.name) &&
this.age == other.age; // примитивы через ==
}
Objects.equals() — это гениальная штука, она сама проверяет на null. Раньше-то писали (field == null ? other.field == null : field.equals(other.field)). Сейчас можно не выёбываться.
И ради всего святого, сравнивай сначала те поля, которые с наибольшей вероятностью различаются. Не надо сначала тяжеловесные объекты или строки в километр тащить. Сравнил id — и сразу false, если не совпали. Экономия процессорного времени, ёбана.
Про hashCode(): Objects.hash() — твой друг. Туда пихаешь те же поля, что и в equals(). Всё, больше ни о чём не думаешь.
@Override
public int hashCode() {
return Objects.hash(name, age);
}
И последнее: если лень это всё писать — поставь Lombok и навесь @EqualsAndHashCode над классом. Он сделает всё за тебя, правильно и без косяков. Но хотя бы раз в жизни напиши это руками, чтобы понимать, как эта магия работает изнутри, а не быть, прости господи, мартышлюшкой, которая тыкает в кнопки.
Запомни: правильно написанные equals() и hashCode() — это фундамент, на котором не проседает вся остальная архитектура. На этом не экономь, а то потом волнение ебать будет, когда продакшн упадёт в три часа ночи.