Как сравнить объекты в java
Для сравнения объектов в Java используется метод equals() . Метод equals() сравнивает содержимое двух объектов на равенство.
По умолчанию метод equals() сравнивает два объекта на идентичность, то есть проверяет, указывают ли они на один и тот же объект в памяти. Однако, часто требуется сравнить объекты по содержимому, а не по ссылке на объект.
Чтобы сравнить объекты по содержимому, необходимо переопределить метод equals() в классе объекта. Для этого нужно реализовать логику сравнения внутри метода, которая определяет, что два объекта равны друг другу.
Например, для класса Person , метод equals() может быть реализован следующим образом:
public class Person private String name; private int age; // конструктор и методы класса @Override public boolean equals(Object obj) if (obj == this) // проверка на идентичность return true; > if (!(obj instanceof Person)) // проверка типа объекта return false; > Person other = (Person) obj; // приведение объекта к типу Person return this.name.equals(other.name) && this.age == other.age; // сравнение содержимого > >
- в данном примере метод equals() сначала проверяет идентичность объектов и тип объекта,
- затем сравнивает содержимое объектов — поля name и age ,
- если оба поля равны у двух объектов, то метод возвращает true , иначе — false . *** Для сравнения объектов также можно использовать оператор == Он проверяет идентичность объектов, то есть указывают ли они на один и тот же объект в памяти. Однако, если объекты имеют разные ссылки на память, но содержат одинаковое содержимое, оператор == вернет false , в то время как метод equals() может вернуть true , если переопределен правильно.
Как сравнить два объекта класса?
Мне нужно сравнить, написать компаратор. По времени уже сравнил, как сравнить по другим полям? Все остальные поля — это enum.
Отслеживать
51.4k 86 86 золотых знаков 267 267 серебряных знаков 505 505 бронзовых знаков
задан 31 окт 2012 в 14:15
2,033 2 2 золотых знака 24 24 серебряных знака 45 45 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Согласно документации при сравнении enum вполне применим оператор как == так и метод equals()
Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant. (The equals method in Enum is a final method that merely invokes super.equals on its argument and returns the result, thus performing an identity comparison.)
Отслеживать
ответ дан 31 окт 2012 в 14:22
81.3k 7 7 золотых знаков 72 72 серебряных знака 153 153 бронзовых знака
И еще такой вопрос — мне нужно отсортировать ArrayList
31 окт 2012 в 14:44
ну так вот и определи все условия для больше, меньше и равны
31 окт 2012 в 14:49
Если вы имплементируете Comparable<> , то можете написать только 1 compareTo() , т.е. сортировать по одному полю. Для сортировки по любому другому полю вы должны использовать версию сортировки с компаратором.
Соответственно, для каждого желаемого поля создавать свой компаратор ( Comparator ) и скармливать его методу sort() . Все методы сравнения так и названы ( compare() или compareTo ), потому что сравнивают, т.е. отвечают на вопрос «кто больше или меньше или равны», поэтому надо прописывать условия для всех случаев.
Не путайте с equals() , который проверяет условия, при которых объекты равны, но не отвечает на вопрос кто больше или меньше.
Отслеживать
51.6k 201 201 золотой знак 63 63 серебряных знака 245 245 бронзовых знаков
ответ дан 5 июл 2017 в 12:31
user224616 user224616
Хоть по всем полям сравнивать в методе compareTo() .
5 авг 2018 в 15:10
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Как сравнить названия классов в java
Как всегда сбалансированные задачи!) Где надо подгорает, где надо сами разберёмся) Заставляет думать и искать, всё как в жизни!
Nikolai Уровень 13
23 декабря 2023
ВНИМАНИЕ. Для задачи про hashCode() вам нужно прочитать лекцию hashCode() and equals()
Anastasia Уровень 14
20 декабря 2023
За 11 уровней, которые я прошла это была самая сложная статья. Разбирала ее 2 дня, мб кому поможет, вот что я поняла для себя: В java есть 4 метода сравнения: Сравнение по адресу == (для цифр) Сравнение по содержимому equals (для строк, текста), Сравнение по проверке через pool (только для текста, работает быстрее чем equals) Сравнение по хэш коду(для объектов, быстрое, но не качественное, вроде как) По содержимому сравнивает equals только строки (String), а если мы создали 2 или больше обьектов и хотим их сравнить, то equals будет их сравнивать как ==, те адрес, а не содержимое, как у String. Поэтому основной посыл, это если мы хотим сравнить 2 обьекта, нам нужно прописать руками методику работы equals. Короче надо просто зазубрить 4 вида кода выше и понять, что каждый из них делает: 1 вариант: Это тот обьект или другой? (код проверяет ссылки ==) 2 вариант. Ссылка обьекта пустая или нет(код проверяет null. Null это аналог 0, но для строк). 3 вариант. Равны ли 2 обьекта из разных классов? (код проверяет названия классов, в которых лежат обьекты(?) через метод getClass или instaseof). 4 вариант. Проверяет содержимое 2 обьектов, что внутри них. Тут нужно сделать приведение типов и потом вручную проверить переменные обоих классов через оператор this + если переменные строки, дополнительно написать еще слово equals и провести проверку на null. Я до конца не уверенна, что это 100% правильно, но как смогла понять((
Валерия Коновалова Уровень 13
19 декабря 2023
А в третьей задаче получается в правильном решении контракт нарушили? непорядок !
Kirill Cheremnykh Уровень 13
17 декабря 2023
В 4 пункте, зачем операция приведения типа «Person person = (Person) obj;», если мы только что проверили, что obj не является не типом Person? Получается, obj уже типа Person? или я что-то не понимаю
Evgeny Makarov Уровень 13
13 декабря 2023
public boolean equals(Object obj) < if (this == obj) return true; остальной код метода equals >А где почитать про this, который сам по себе, а не this.a или this.b?
Louis d’Ipinaisse Уровень 14
12 декабря 2023
для тех кто как и я не понял, в чем разница между
Object.equals(obj_1, obj_2)
obj_1.equals(obj_2)
Сравнение объектов в Java

Сравнение объектов является важной функцией объектно-ориентированных языков программирования. В этом руководстве мы рассмотрим некоторые функции языка Java, которые позволяют нам сравнивать объекты. Также мы обратим внимание на подобные функции во внешних библиотеках.
Операторы == и !=
Давайте начем с операторов == и != , которые могут сказать, одинаковы ли Java-объекты или нет соответственно.
Примитивы
Для примитивных типов быть одинаковым означает иметь одинаковые значения:
assertThat(1 == 1).isTrue();
Благодаря автоматической распаковке это также работает при сравнении примитивного значения с его классом-оберткой:
Integer a = new Integer(1); assertThat(1 == a).isTrue();
Если две целочисленные переменные имеют разные значения, оператор == вернет false , а оператор != вернет true .
Объекты
Предположим, мы хотим сравнить два экземпляра классов-оберток Integer с одинаковыми значениями:
Integer a = new Integer(1); Integer b = new Integer(1); assertThat(a == b).isFalse();
При сравнении двух объектов их значения не равняются 1. Скорее различаются их адреса памяти в стеке, поскольку оба объекта создаются с использованием оператора new . Если мы присвоим переменной а переменную b , то получим другой результат:
Integer a = new Integer(1); Integer b = a; assertThat(a == b).isTrue();
Теперь давайте посмотрим, что происходит, когда мы используем фабричный метод Integer#valueOf :
Integer a = Integer.valueOf(1); Integer b = Integer.valueOf(1); assertThat(a == b).isTrue();
В этом случае они считаются одинаковыми. Это связано с тем, что метод valueOf() держит Integer в кеше, чтобы избежать создания слишком большого количества оберток с одинаковыми значениями. Поэтому метод возвращает один и тот же экземпляр Integer для обоих вызовов.
Java также делает это для переменных типа String:
assertThat("Hello!" == "Hello!").isTrue();
Однако, если они созданы с помощью оператора new , они не будут одинаковыми.
Наконец, две нулевые ссылки считаются одинаковыми, в то время как любой не-null объект считается отличным от null:
assertThat(null == null).isTrue(); assertThat("Hello!" == null).isFalse();
Конечно, поведение операторов равенства может быть ограничивающим. Что если мы хотим сравнить два объекта, расположенных по разным адресам и при этом полагать, что они равны на основании их внутренних состояний? Как это сделать, мы увидим в следующих пунктах.
Метод Object#equals
Теперь давайте поговорим о более широком концепте равенства с методом equals() .
Этот метод определен в классе Object , поэтому каждый объект Java наследует его. По умолчанию его реализация сравнивает адреса памяти объектов, поэтому он работает так же, как и оператор == . Однако мы можем переопределить этот метод, чтобы определить, что для наших объектов означает равенство внутренних состояний.
Во-первых, давайте посмотрим, как он ведет себя для существующих объектов, таких как Integer:
Integer a = new Integer(1); Integer b = new Integer(1); assertThat(a.equals(b)).isTrue();
Наш метод по-прежнему возвращает true, когда оба объекта одинаковы.
Отметим здесь, что мы можем передать объект null в качестве аргумента метода, но не в качестве объекта, для которого мы вызываем метод.
Мы также можем использовать метод equals() с любым пользовательским объектом. Допустим, у нас есть класс Person:
public class Person < private String firstName; private String lastName; public Person(String firstName, String lastName) < this.firstName = firstName; this.lastName = lastName; >>
Мы можем переопределить метод equals() для этого класса, чтобы мы могли сравнить два объекта Persons на основе их внутренних данных:
@Override public boolean equals(Object o)
Чтобы узнать больше по этой теме, читайте вот эту статью.
Статический метод Objects#equals
Давайте посмотрим на статический метод Objects#equals . Ранее мы упоминали, что нельзя использовать null в качестве значения первого объекта, иначе будет выброшено исключение NullPointerException .
Метод equals() вспомогательного класса Objects решает эту проблему. Он принимает два аргумента и сравнивает их, а также обрабатывает значения null.
Давайте снова сравним объекты Person :
Person joe = new Person("Joe", "Portman"); Person joeAgain = new Person("Joe", "Portman"); Person natalie = new Person("Natalie", "Portman"); assertThat(Objects.equals(joe, joeAgain)).isTrue(); assertThat(Objects.equals(joe, natalie)).isFalse();
Как мы объяснили, этот метод обрабатывает значения null. Следовательно, если оба аргумента равны null, он вернет значение true, а если только один из них равен null, он вернет значение false.
Это может быть очень удобно. Допустим, мы хотим добавить не строго обязательную дату рождения в наш класс Person :
public Person(String firstName, String lastName, LocalDate birthDate)
Затем нужно обновить метод equals() , но с обработкой null значений. Мы можем сделать это, добавив условие в метод equals() :
birthDate == null ? that.birthDate == null : birthDate.equals(that.birthDate);
Однако же, если мы добавим слишком много полей с возможными null значениями в класс, он может стать запутанным. Использование метода Objects#equals в реализации equals() намного чище, что улучшает читаемость кода.
Objects.equals(birthDate, that.birthDate);
Интерфейс Comparable
Логику сравнения также можно использовать для размещения объектов в определенном порядке. Интерфейс Comparable позволяет нам определять порядок между объектами, выявляя, является ли объект больше, меньше или равным другому.
Интерфейс Comparable является дженериком и имеет только один метод, compareTo() , который принимает аргумент дженерик-типа и возвращает int. Возвращаемое значение отрицательное, если this меньше аргумента, 0, в случае если они равны, и положительное в обратном случае.
Допустим, в классе Person мы хотим сравнить объекты Person по их фамилии:
public class Person implements Comparable < //. @Override public int compareTo(Person o) < return this.lastName.compareTo(o.lastName); >>
Метод compareTo() вернет отрицательный int, если оно вызвано с именем Person , имеющим большую фамилию, чем this, ноль, если ту же фамилию, и положительное значение в обратном случае.
Чтобы узнать подробнее, прочитайте статью на эту тему.
Интерфейс Comparator
Интерфейс Comparator является дженериком и содержит метод compare , который принимает два аргумента этого типа и возвращает integer. Мы ранее уже видели этот шаблон с интерфейсом Comparable.
Comparator аналогичен ему; однако он отделен от определения класс. Следовательно, мы можем определить столько Comparator , сколько захотим для одного класса, где мы можем предоставить только одну реализацию Comparable .
Представим, что у нас есть веб-страница, содержащая список людей в виде таблицы, и мы хотим предложить пользователю возможность сортировать их по именам, а не по фамилиям. Это невозможно с Comparable , если мы также хотим сохранить нашу текущую реализацию, но мы можем реализовать наши собственные Comparators .
Давайте создадим Person Comparator , который будет сравнивать их только по именам:
Comparator compareByFirstNames = Comparator.comparing(Person::getFirstName);
Теперь отсортируем список людей, используя Comparator :
Person joe = new Person("Joe", "Portman"); Person allan = new Person("Allan", "Dale"); List people = new ArrayList<>(); people.add(joe); people.add(allan); people.sort(compareByFirstNames); assertThat(people).containsExactly(allan, joe);
В интерфейсе Comparator есть и другие методы, которые мы можем использовать в реализации compareTo() :
@Override public int compareTo(Person o)
В этом примере мы сначала сравниваем фамилии, а затем имена. Затем мы сравниваем даты рождения, но, поскольку они нулевые, нужно рассказать, что с этим делать. Для этого мы задаем второй аргумент, чтобы сказать, что их нужно сравнить в соответствии с их естественным порядком, причем значения null идут последними.
Apache Commons
Давайте взглянем на библиотеку Apache Commons. Прежде всего, импортируем зависимость Maven.
org.apache.commons commons-lang3 3.12.0
Метод ObjectUtils#notEqual
Для начала поговорим о методе ObjectUtils#notEqual . Потребуется два аргумента Object , чтобы определить, не равны ли они, в соответствии с их собственной реализацией метода equals() . Он также обрабатывает значения null.
Используем наши примеры со String повторно:
String a = new String("Hello!"); String b = new String("Hello World!"); assertThat(ObjectUtils.notEqual(a, b)).isTrue();
Следует отметить, что у ObjectUtils есть метод equals() , что однако является устаревшим с момента возникновения Java 7, когда появились Objects#equals .
Метод ObjectUtils#compare
Теперь давайте сравним порядок объектов с помощью метода ObjectUtils#compare . Это дженерик-метод, который принимает два аргумента Comparable дженерик типа и возвращает Integer.
Приведем пример, снова используя Strings:
String first = new String("Hello!"); String second = new String("How are you?"); assertThat(ObjectUtils.compare(first, second)).isNegative();
По умолчанию этот метод обрабатывает значения null, считая их бОльшими. Он также предлагает перегруженную версию с аргументом boolean, которая предлагает изменить это поведение и считать их мЕньшими, принимая аргумент boolean.
Guava
Давайте взглянем на Guava. Прежде всего импортируем зависимость:
com.google.guava guava 31.0.1-jre
Метод Objects#equal
Как и библиотека Apache Commons, Google предоставляет нам метод определения равенства двух объектов, Objects#equal . Хотя у них разные реализации, возвращают они одинаковые результаты:
String a = new String("Hello!"); String b = new String("Hello!"); assertThat(Objects.equal(a, b)).isTrue();
Хотя он не помечен как устаревший, в JavaDoc говорится, что этот метод следует считать устаревшим, поскольку Java 7 предоставляет метод Objects#equals .
Методы сравнения
Библиотека Guava не предлагает метода для сравнения двух объектов (в следующем разделе мы увидим, что мы можем для этого сделать), но она предоставляет нам методы для сравнения примитивных значений. Давайте возьмем вспомогательный класс Ints и посмотрим, как работает его метод compare() :
assertThat(Ints.compare(1, 2)).isNegative();
Как обычно, он возвращает integer, который может быть отрицательным, нулевым или положительным, если первый аргумент меньше, равен или больше второго соответственно. Подобные методы существуют для всех примитивных типов, за исключением bytes.
Класс ComparisonChain
Наконец, библиотека Guava предлагает класс ComparisonChain , который позволяет нам сравнивать два объекта по цепочке сравнений. Мы можем легко сравнить два объекта Person по имени и фамилии:
Person natalie = new Person("Natalie", "Portman"); Person joe = new Person("Joe", "Portman"); int comparisonResult = ComparisonChain.start() .compare(natalie.getLastName(), joe.getLastName()) .compare(natalie.getFirstName(), joe.getFirstName()) .result(); assertThat(comparisonResult).isPositive();
Базовое сравнение достигается с помощью метода compareTo() , поэтому аргументы, передаваемые методам compare() , должны быть либо примитивными, либо Comparable.
Заключение
В этой статье мы узнали о разных способах сравнения объектов в Java. Мы изучили разницу между тождественностью, равенством и порядком. Мы также рассмотрели соответствующие функции в библиотеках Apache Commons и Guava.
Полный код из статьи можно найти на GitHub.
Приглашаем всех желающих на открытое занятие «Языки статической и динамической типизации». На этом вебинаре поговорим о стилях программирования и необходимости каждого из них. Разберём основные принципы объектно-ориентированного стиля (Инкапсуляция, Наследование, Полиморфизм). Рассмотрим возможности функционального стиля, которые предоставляет язык Java. Регистрация на вебинар.