Relationship between hashCode and equals method in Java [duplicate]
Связь между хэш-кодом и методом equals в Java
Я читал во многих местах, что при переопределении equals метода в Java также следует переопределять hashCode метод, иначе это "нарушает контракт".
Но пока я не сталкивался с какой-либо проблемой, если я переопределяю только метод equals, но не метод hashCode.
Что такое контракт? И почему я не сталкиваюсь с какими-либо проблемами, когда нарушаю контракт? В каком случае я столкнусь с проблемой, если я не переопределил метод hashCode?
Переведено автоматически
Ответ 1
Проблема, с которой вы столкнетесь, связана с коллекциями, где уникальность элементов вычисляется в соответствии с обоими .equals() и .hashCode(), например, ключами в a HashMap.
Как следует из его названия, он полагается на хэш-таблицы, а хэш-сегменты являются функцией объекта .hashCode().
Если у вас есть два объекта, которые являются .equals(), но имеют разные хэш-коды, вы проиграли!
Важная часть контракта здесь такова: объекты, которые являются .equals(), ДОЛЖНЫ иметь одинаковое значение .hashCode().
Согласно документу , реализация hashCode по умолчанию вернет некоторое целое число, которое отличается для каждого объекта
Насколько это разумно практично, метод hashCode, определенный class Object, возвращает разные целые числа для разных объектов. (Обычно это реализуется путем преобразования внутреннего адреса объекта в целое число, но эта реализация техника не требуется языком программирования JavaTM.)
Однако в какой-то момент вы захотите, чтобы хэш-код был одинаковым для разных объектов, имеющих одинаковое значение. Например
Students1=newStudent("John", 18); Students2=newStudent("John", 18); s1.hashCode() != s2.hashCode(); // With the default implementation of hashCode
Такого рода проблемы будут возникать, если вы используете хэш-структуру данных в фреймворке сбора данных, такую как HashTable, HashSet. Особенно с такой коллекцией, как HashSet, в конечном итоге вы получите дублирующий элемент и нарушите установленный контракт.
Ответ 3
Да, это должно быть переопределено. Если вы считаете, что вам нужно переопределить equals(), то вам нужно переопределить hashCode() и наоборот. Общий контракт hashCode() заключается в:
Всякий раз, когда он вызывается для одного и того же объекта более одного раза во время выполнения Java-приложения, метод hashCode должен последовательно возвращать одно и то же целое число при условии, что информация, используемая в сравнениях equals для объекта, не изменена. Это целое число не обязательно должно оставаться согласованным от одного выполнения приложения к другому выполнению того же приложения.
Если два объекта равны в соответствии с методом equals(Object), то вызов метода hashCode для каждого из двух объектов должен приводить к одному и тому же целочисленному результату.
Необязательно, что если два объекта неравны в соответствии с методом equals (java.lang.Object), то вызов метода hashCode для каждого из двух объектов должен давать разные целочисленные результаты. Однако программист должен знать, что получение различных целочисленных результатов для неравных объектов может повысить производительность хэш-таблиц.
Ответ 4
Взгляните на Hashtables, Hashmaps, HashSets и так далее. Все они хранят хэшированный ключ в качестве своих ключей. При вызове get(Object key) генерируется хэш параметра и выполняется поиск в заданных хэшах.
Когда перезапись не выполняется hashCode() и экземпляр ключа был изменен (например, простая строка, которая вообще не имеет значения), hashCode() может привести к появлению двух разных хэш-кодов для одного и того же объекта, что приведет к невозможности нахождения данного ключа в map.get().