Что такое equals

Ответ

Метод equals() в Java используется для сравнения объектов на содержательное равенство, в отличие от ==, который сравнивает ссылки.

Переопределение equals() должно учитывать:

  • Рефлексивность: a.equals(a) == true
  • Симметричность: a.equals(b) == b.equals(a)
  • Транзитивность: если a.equals(b) и b.equals(c), то a.equals(c)
  • Консистентность: повторные вызовы дают одинаковый результат
  • Неравенство с null: a.equals(null) == false

Пример:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

Всегда переопределяйте hashCode(), если переопределяете equals()!

Ответ 18+ 🔞

А, ну вот, опять про этот equals() заговорили. Слушай, давай я тебе на пальцах объясню, а то смотрю, народ путается в этих дебрях, как слепой кот в подвале.

Представь себе, что у тебя два одинаковых телефона. Один лежит у тебя в кармане, другой — у меня. По == они разные, потому что это два разных куска пластика и кремния в пространстве, ёпта. А по equals() — одинаковые, потому что модель одна, память одинаковая, и камера у обоих хреновая. Вот и вся магия. == смотрит, один ли это объект в памяти, а equals()одинаковые ли у них данные внутри.

Теперь про переопределение. Это, блядь, целая наука, тут нельзя просто так взять и написать if (a.name == b.name). Надо соблюдать правила, а то получится пиздопроебибна, и коллекции твои сломаются, как карточный домик.

Вот на что забить надо:

  • Рефлексивность: Объект должен быть равен самому себе. a.equals(a) — всегда true. Если это не так, то ты, прости, ебанько, иди код переписывай.
  • Симметричность: Если я тебе равен, то и ты мне равен. a.equals(b) и b.equals(a) должны давать один и тот же результат. Иначе будет волнение ебать, когда ты положишь a в HashSet, а потом b в нём не найдёшь, хотя они, по-твоему, "одинаковые".
  • Транзитивность: Если a равен b, а b равен c, то a обязан быть равен c. Иначе логика просто накрывается медным тазом.
  • Консистентность: Сколько раз ни вызывай equals() — результат должен быть один и тот же, если данные не менялись. Нельзя, чтобы он сегодня говорил true, а завтра — false на тех же самых объектах. Доверия ебать ноль к такому методу будет.
  • С null всегда false: a.equals(null) — должно возвращать false, а не NullPointerException. Это святое.

Вот, смотри, как это обычно выглядит в коде, на примере какого-нибудь класса Person:

@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. Ну ок, раз класс один, кастуй смело.
    Person person = (Person) o;

    // 4. Сравнивай все значимые поля. Возраст примитив — через ==, имя (String) — через Objects.equals(), он сам null проверяет.
    return age == person.age && Objects.equals(name, person.name);
}

И вот теперь, внимание, главное правило, которое все забывают, а потом охуевают:

Если переопределил equals() — БЛЯДЬ, ПЕРЕОПРЕДЕЛИ И hashCode()!

Серьёзно, ёпта. Иначе твои объекты в HashMap или HashSet превратятся в тыкву. Они будут считаться разными, даже если equals() говорит, что они одинаковые. Коллекции используют хэш-код как быстрый фильтр, и если у двух "равных" объектов хэш-коды разные — их даже сравнивать equals() не станут. Всё, пиши пропало. Так что не будь распиздяем, делай всё по уму.