2015-03-20 3 views
-1

Я знаю, что когда мы переопределяем метод equals(), нам необходимо переопределить hashcode() так же, как и наоборот.Hashcode и equals methods contract

Но я не понимаю, почему мы ДОЛЖНЫ сделать это?

В Джошуа Блох Книга ясно написано, что мы необходимо сделать это, потому что, когда мы имеем дело с хэш на основе коллекций, это имеет решающее значение для удовлетворения Hashcode контракт и я признаю, что, но что если я не имею дело с хэш-коллекциями?

Почему это все еще требуется?

+0

Поскольку любые два объекта, которые являются «равными», ДОЛЖНЫ, по определению, иметь один и тот же «хэш-код», как они могут быть «равными» в противном случае? – MadProgrammer

+0

Потому что когда-нибудь вы * будете * пытаться набить его в хэш-сбор, даже если только косвенно. Это скрытая ошибка, которую легко избежать. – chrylis

+0

Потому что кто-то еще может. Или вы, в будущем. Это эквивалентно наличию 'int subtract (a, b) {return a + b; } 'в вашем коде. Вы можете вспомнить это сейчас, но если ваш код станет больше или получит нового разработчика ... Ой. Если вы не сожжете его, это только к счастью. – Amadan

ответ

0

Согласно Joshua Bloch книги;

Общим источником ошибок является отказ от переопределения метода hashCode . Вы должны переопределить hashCode в каждом классе, который переопределяет равно. Несоблюдение этого требования приведет к нарушению общего договора для Object.hashCode, который предотвратит функционирование вашего класса с в сочетании со всеми коллекциями, основанными на хэше, , включая HashMap, HashSet и Hashtable.

Неспособность переопределить hashcode при переопределении равных является нарушением договора Object.hashCode. Но это не повлияет, если вы используете свои объекты только в коллекции, не содержащей хэш.

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

0

Потому что это способ, которым это предназначается, чтобы быть:

Всякий раз, когда a.equals (б), то a.hashCode() должны быть такими же, как b.hashCode().

What issues should be considered when overriding equals and hashCode in Java?

Есть потребительные случаи, когда вам не нужно hashcode(), в основном самостоятельно написанный scenarious, но вы никогда не можете быть уверены, потому что реализация может и может быть также полагаться на hashcode(), если они используя equals()

0

Структуры данных, такие как HashMap, зависят от договора.

HashMap достигает магических характеристик производительности, используя hashcode для ввода букв. Каждый элемент, который помещается на карту с таким же значением hashcode(), помещается в одно ведро. Эти «столкновения» разрешаются путем сравнения в одном и том же ведре с использованием equals(). Другими словами, хэш-код используется для определения подмножества элементов на карте, которые могут быть равными, и таким образом быстро устранить подавляющее большинство предметов из дальнейшего рассмотрения.

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

ПРИМЕЧАНИЕ. На практике число столкновений намного выше, чем может быть указано выше, так как количество используемых ковшей обязательно намного меньше, чем количество возможных значений хэш-кода.

1

Зачем перекрывать равные?

Программист, который сравнивает ссылки на объекты стоимостью, используя метод equals ожидает, чтобы выяснить, являются ли они логически эквивалентны, не , относятся ли они к тому же объекту.

Сейчас подходит к HashCode

Функция хеширования, который призван производить хэш-код должен вернуть same хэш-код каждый раз, когда функция применяется на одинаковые или равные объекты. Другими словами, два равных объекта должны последовательно создавать один и тот же хэш-код.

Осуществление HashCode обеспечивается Object Class не основано на logical equivalency,

Так вот, если вы не перекроет hashCode но переопределить equals, то в соответствии с вами 2 объектов равны, как они будут проходить тест equals() но в соответствии с Java они не являются.

Последствия:

  1. Set старт позволяет дубликаты !!!
  2. Map#get(key) не вернет правильное значение !!
  3. и так на многих других consquences ..................
0

Этот вопрос много раз отвечает в SO, но все же я попытаюсь ответить на это.

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

equals метод используется для определения равенства объекта. Для примитивных типов очень легко определить равенство. Мы можем легко сказать, что int 1 всегда равен 1. Но этот равный метод говорит о равенстве объектов. Равенство объекта зависит от переменных экземпляра или любого другого параметра (зависит только от реализации - как вы хотите сравнить).

Этот равный метод необходимо переопределить, если мы хотим провести какое-то индивидуальное сравнение, скажем, мы хотим сказать, что две книги одинаковы, если они имеют одинаковый заголовок и тот же автор, или я могу сказать, что две книги равны, если они имеют одинаковые ISBN.

hashcode метод возвращает значение хэш-кода объекта. По умолчанию реализация hashcode объекта возвращает отдельные целые числа для отдельных объектов. Это целое число вычисляется на основе адреса памяти объекта.

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

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

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

Смежные вопросы