2013-04-17 3 views
25

У меня есть два java-объекта, которые создаются из одного класса.Как сравнить два java-объекта

MyClass myClass1 = new MyClass(); 
MyClass myClass2 = new MyClass(); 

Если установить оба их свойств тех же значений, а затем проверить, что они такие же

if(myClass1 == myClass2){ 
    // objects match 
    ... 

} 

if(myClass1.equals(myClass2)){ 
    // objects match 
    ... 

} 

Однако ни один из этих подходов возвращает истинное значение. Я проверил свойства каждого и они совпадают.

Как сравнить эти два объекта, чтобы убедиться, что они идентичны?

+0

Я сделал это Google, но все примеры, которые я нашел, никогда не объясняли, что вам пришлось переопределить метод equals. –

+0

@AndroidAddict: Так почему вы не задали этот вопрос? – 2013-04-17 20:18:01

ответ

71

Вы должны предоставить собственную реализацию equals() в MyClass.

@Override 
public boolean equals(Object other) { 
    if (!(other instanceof MyClass)) { 
     return false; 
    } 

    MyClass that = (MyClass) other; 

    // Custom equality check here. 
    return this.field1.equals(that.field1) 
     && this.field2.equals(that.field2); 
} 

Вы должны также переопределить hashCode(), если есть какой-то шанс из ваших объектов, используемых в хэш-таблице. reasonable implementation бы объединить хэш-коды полей объекта с чем-то вроде:

@Override 
public int hashCode() { 
    int hashCode = 1; 

    hashCode = hashCode * 37 + this.field1.hashCode(); 
    hashCode = hashCode * 37 + this.field2.hashCode(); 

    return hashCode; 
} 

См this question для более подробной информации о реализации хэш-функции.

+1

Почему 37? Премьер? – Aubin

+1

@Aubin Обычно в генерации хэш-кода используются простые числа. Если я не ошибаюсь, это уменьшает вероятность столкновения с генерируемыми хэшами. Что касается использования 37, я думаю, это просто популярный выбор, я не знаю какой-либо конкретной причины для использования 37, а не, скажем, 13. – afsantos

+0

Спасибо - все на самом деле. Все поместили меня на правильный путь, но я могу только принять его правильно. –

5

Вы должны правильно переопределить метод Equals() из класса Object

Edit: Я думаю, что мой первый ответ был неправильно понят, вероятно, потому, что я был не слишком точным. Поэтому я решил добавить больше объяснений.

Почему вы должны переопределить equals()? Хорошо, потому что это в домене разработчика, чтобы решить, что означает, что для двух объектов будут равными. Для большинства случаев стандартного равенства недостаточно.

Например, представьте, что у вас есть HashMap, ключи которого имеют тип Person. У каждого человека есть имя и адрес. Теперь вы хотите найти подробный компонент, используя ключ. Проблема в том, что вы обычно не можете создать экземпляр с той же ссылкой, что и на карте. Что вы делаете, так это создать еще один экземпляр класса Person. Очевидно, оператор == не будет работать здесь, и вы должны использовать equals().

Но теперь мы приходим к другой проблеме. Представим себе, что ваша коллекция очень большая, и вы хотите выполнить поиск. Наивная реализация сравнивала бы ваш ключевой объект с каждым экземпляром на карте с помощью equals(). Это, однако, было бы очень экспансивным. И вот идет hashCode(). Как отмечали другие, hashcode - это единственный номер, который не обязательно должен быть уникальным. Важным требованием является то, что всякий раз, когда equals() дает true для двух объектов, hashCode() должен возвращать одинаковое значение для обоих из них. Обратная импликация не выполняется, что хорошо, потому что hashcode разделяет наши ключи на ведра. У нас есть небольшое количество экземпляров класса Person в одном ведре. Когда мы выполняем поиск, алгоритм может сразу перейти в правильное ведро и только теперь выполнить равный для каждого экземпляра. Поэтому реализация hashCode() должна распределять объекты как можно более равномерно по ковши.

Есть еще один момент. Некоторые коллекции требуют правильной реализации метода hashCode() в классах, которые используются как ключи не только по соображениям производительности. Примеры: HashSet и LinkedHashSet. Если они не переопределяют hashCode(), метод hashCode() объекта Object допускает несколько объектов, которые вы можете считать «значимо равными», которые будут добавлены к вашему «без дубликатов».

Некоторые из коллекций, которые используют хэш-код()

  • HashSet
  • LinkedHashSet
  • HashMap

Взгляните на этих двух классов от Apache Commons, которые позволяют реализовать equals() и hashCode() легко

7

Вам необходимо переопределить equals и hashCode.
equals будет сравнивать объекты равенства в соответствии со свойствами, которые нужны и hashCode является обязательным для того, чтобы ваши объекты должны быть правильно использованы в Collections и Maps

2

1) == оценивает равенство ссылок в этом случае
2) im не слишком уверен в равных, но почему бы не просто переопределить метод сравнения и установить его в MyClass?

5

Вам необходимо реализовать метод equals() в вашем MyClass.

Причина, по которой == не работает, это проверка того, что они относятся к одному экземпляру. Так как вы сделали new для каждого, каждый из них является другим экземпляром.

Причина, по которой equals() не работает, потому что вы ее еще не реализовали. Я считаю, что поведение по умолчанию - это то же самое, что и ==.

Обратите внимание, что вы также должны реализовать hashcode(), если вы собираетесь реализовать equals(), потому что много java.util Коллекций ожидает этого.

+0

Хорошее объяснение. Короче и точно. – tommyO