2015-04-29 3 views
3

Я решил изучить некоторые основные документы на Java. Я начал с класса Object, и я смотрю на метод equals. Я знаю, что equals использует метод hashCode. Хотя, hashCode возвращает int, поэтому существует ограниченное количество уникальных хэш-кодов, которые могут быть сгенерированы.Какую роль играет hashCode при сравнении двух объектов?

Что произойдет, когда я попытаюсь сравнить два разных объектов, которые имеют одинаковые hashCode? Это даже возможно?

+4

'equals' не использует' hashCode'. Хотя, у них есть контракт между собой, который должен быть соблюден. – CKing

+0

равные объекты должны иметь одинаковый хэш-код, но не наоборот. –

+0

Когда вы определяете equals или compareTo (когда вы переопределяете эти методы из класса Object), вы должны быть уверены, что два объекта, которые вы сравниваете, относятся к одному классу с примером instanceof(). a.equals (b) => a.hashCode() == b.hashCode(); Но a.hashCode() == b.hashCode! => A.equals (b); – Shondeslitch

ответ

3

Да. Два объекта могут иметь один и тот же хэш-код. Однако hashcode не играет никакой роли при сравнении двух объектов. Если вы хотите проверить, являются ли два объекта класса equal, переопределите equals и определите, когда два объекта класса должны считаться равными. Если вы хотите сравнить, если один объект класса меньше/больше другого (обычно при сортировке коллекции), выполните Comparable и переопределите метод compareTo. (Вы также можете реализовать Comparator)

Если вы когда-либо хотите сохранить объект в HashSet или использовать его в качестве ключа в HashMap, убедитесь, что вы переопределить метод hashCode или ваши объекты/ключи, скорее всего, будут сохранены в разных ведрах, что приводит к дублированию.

Не забудьте переопределить equals в классах, которые вы создаете. Если вы этого не сделаете, две ссылки на объект вашего класса будут равны, если они относятся к одному и тому же объекту.

Подробнее о методах equals и hashCode можно найти в документации equals и hashCode.

+0

». Я считаю, что ваше утверждение, что' Object.equals() 'вызовет все объекты в' HashSet 'или все ключи в' HashMap', которые будут храниться в одном ведре, неверны. На странице javadocs, на которую вы ссылаетесь, указано, что 'Object.equals()' возвращает уникальные целые числа для уникальных объектов. –

+0

@SteveBrandli Можете ли вы указать мне на часть моего ответа, утверждающую, что ** Object.equals ** заставит ключи храниться в одном ведре? Кажется, я не могу найти это в приведенном выше ответе. Вы имели в виду 'hashCode', в этом случае вы правы. Исправлен ответ – CKing

+0

Опять же, * «... hashcode не играет никакой роли при сравнении двух объектов» * не совсем правильно. – scottb

0

Контракт hashcode() довольно прост:

  • Если два объекта равны по методу Equals, то вызов метода Hashcode на каждом из двух объектов должен производить тот же целочисленный результат.

  • Не требуется, чтобы, если два объекта неравны в соответствии с методом equals, то вызов метода hashCode для каждого из двух объектов должен производить различные целочисленные результаты.

Действительный хэш-функции для любого класса объектов может поэтому быть:

@Override 
public int hashcode() { 
    return 42; 
} 

договора, равные объекты имеют одинаковое значение хэш-код выполняется.

Проблема заключается в том, что классы, использующие вышеупомянутый хэш-код для распространения объектов в ковши (например, HashSet), будут распределять все объекты в одном и том же ковше с серьезными последствиями для производительности. Оптимальная хеш-функция, хотя и не строго обязательная, создавала бы различные значения для неравных объектов, чтобы они были распределены по собственным ведрам.

Контракт на Object.equals() не требует использования hashcode() при проведении сравнений. Однако, если неизменяемый объект имеет дорогостоящее сравнительное сравнение, он может использовать значение хэш-кода для определения необходимости дорогостоящего сравнения. Хэш-код можно кэшировать при первом вычислении.Поскольку объект неизменен, хэш-код не может меняться, и поэтому он может быть безопасно кэширован в экземпляре. Поэтому хэш-код можно использовать в качестве оптимизации для сравнений равных: дорогостоящее сравнение нужно делать только для экземпляров с одним и тем же хэш-кодом.

Простые алгоритмы для написания адекватных хэш-функций можно найти в Effective Java, 3rd Ed. (Дж. Блох). Современные IDE также могут автоматически генерировать хеш-функции для вас.