Равные объекты должны иметь одинаковые хеш-коды? - PullRequest
1 голос
/ 07 августа 2011

Равные объекты должны иметь одинаковые хэш-коды. Насколько я понимаю, это утверждение действительно, когда мы собираемся использовать объект в основанных на хэше данных. Это один из контрактов на хэш-код и метод equals в документации Java. Я исследовал причину, по которой это сказано, и посмотрел в реализации хеш-таблицы и обнаружил приведенный ниже код в put методе

if ((e.hash == hash) && e.key.equals(key)) 

Итак, я понял, контракт пришел из условия e.hash == hash выше. Далее я попытался выяснить, почему java проверяет хеш-код при сравнении двух объектов на равенство. Так вот мое понимание

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

  • Лучше проверять хэш-код, чем фактически вызывать метод equals, потому что метод hascode дешевле, чем метод equals, потому что здесь мы просто должны сравнить значение int, где в методе equals может использоваться сравнение полей объекта. Так что метод хэш-кода обеспечивает один дополнительный фильтр.

Пожалуйста, исправьте меня, если обе вышеуказанные причины действительны?

Ответы [ 4 ]

7 голосов
/ 07 августа 2011
  1. Правильно, только небольшая поправка - если два неравных объекта имеют одинаковый хеш-код.
  2. Не совсем, лучше сначала проверить это, как фильтр для не- равный, но если вы хотите убедиться, что объекты равны, вы должны вызвать equals()
4 голосов
/ 07 августа 2011

Вы ошиблись. equals просто возвращает логическое значение (два возможных значения) и нуждается в другом объекте для сравнения. hashCode возвращает целое число (2 ^ 32 возможных значения) и требует только вызова объекта.

HashMap пытается распределить все объекты, которые он содержит, между сегментами. Когда put вызывается на карте, он должен решить, какое ведро он будет использовать для данного объекта. Таким образом, он использует hashCode (по модулю количества сегментов), чтобы решить, какой сегмент использовать. Затем, когда корзина найдена, она должна проверить, есть ли ключ на карте или нет. Для этого он сравнивает каждый объект в корзине с объектом, помещаемым на карту. И для этого он использует equals. Если объект не найден, он добавляет его в корзину.

hashCode не используется, потому что он быстрее, чем equals. Он используется потому, что позволяет распределять ключи по наборам. И гораздо быстрее вычислить hashCode один раз и сравнить объект с (надеюсь) 0, одним или двумя объектами в одном сегменте, чтобы сравнить объект с тысячами объектов, уже сохраненных на карте.

0 голосов
/ 16 января 2017

Это общий тип контракта, поэтому, когда мы храним объекты в структуре данных на основе хеширования, мы всегда должны последовательно помещать или получать один и тот же объект в хеш-таблицу и из нее. Это контракт, который мы создали, чтобы следовать ему так, чтобы процессы ввода / вывода происходили гладко.

0 голосов
/ 05 декабря 2016

«Я также попытался выяснить, почему java проверяет хэш-код при сравнении двух объектов на равенство». Метод put не просто проверяет равенство, он пытается сначала сузить круг, а затем использовать равенства. Вот почему нам нужно объединить HashCode с Equals в случае коллекций с разбивкой.

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

Obj1.equals (Obj2) никогда не будет использовать метод хеш-кода по умолчанию.

...