Недавно я прочитал этот документ Developer Works .
Документ посвящен определению, hashCode()
а также equals()
эффективному и правильному определению, однако я не могу понять, почему мы должны переопределить эти два метода.
Как я могу принять решение для эффективной реализации этих методов?
Ответы:
Джошуа Блох говорит об эффективной Java
Давайте попробуем понять это на примере того, что произойдет, если мы переопределим
equals()
без переопределенияhashCode()
и попытаемся использовать aMap
.Скажем, у нас есть такой класс, и что два объекта
MyClass
равны, если ониimportantField
равны (с помощьюhashCode()
иequals()
сгенерированы затмением)Только переопределить
equals
Если только
equals
переопределено, то приmyMap.put(first,someValue)
первом вызове будет хеш для некоторого сегмента, а при вызове -myMap.put(second,someOtherValue)
хеш для другого сегмента (так как у них другойhashCode
). Таким образом, хотя они равны, поскольку они не хешируют одно и то же ведро, карта не может этого понять, и они оба остаются на карте.Хотя нет необходимости переопределять,
equals()
если мы переопределяемhashCode()
, давайте посмотрим, что произойдет в этом конкретном случае, когда мы знаем, что два объектаMyClass
равны, если ониimportantField
равны, но мы не переопределяемequals()
.Только переопределить
hashCode
Представь, что у тебя есть это
Если вы переопределяете только
hashCode
то, что при вызовеmyMap.put(first,someValue)
он занимает первое место, вычисляет егоhashCode
и сохраняет в заданном сегменте. Затем при вызовеmyMap.put(second,someOtherValue)
его следует заменить первым на второе, как указано в документации к карте, потому что они равны (согласно бизнес-требованиям).Но проблема в том, что функция equals не была переопределена, поэтому, когда карта хэширует
second
и выполняет итерации по сегменту, проверяя, есть ли такой объектk
, которыйsecond.equals(k)
является истинным, он не найдет ни одного, какsecond.equals(first)
будетfalse
.Надеюсь, это было ясно
источник
if you think you need to override one, then you need to override both of them
неправильно. Вы должны переопределить,hashCode
если ваш класс переопределяет,equals
но обратное неверно.equals
будет нарушать контракт, изложенный в javadocObject
: «Если два объекта равны в соответствии сequals(Object)
методом, то вызовhashCode
метода для каждого из двух объектов должен привести к одному и тому же целочисленному результату». Конечно, не все части контрактов выполняются во всем коде, но, формально говоря, это нарушение, и я бы посчитал это ошибкой, ожидающей своего появления.Коллекции, такие как
HashMap
иHashSet
используют значение хеш-кода объекта, чтобы определить, как он должен храниться в коллекции, и хеш-код используется снова, чтобы найти объект в его коллекции.Хеширование поиска состоит из двух этапов:
hashCode()
)equals()
)Вот небольшой пример того, почему мы должны переопределить
equals()
иhashcode()
.Рассмотрим
Employee
класс с двумя полями: возраст и имя.Теперь создайте класс, вставьте
Employee
объект вHashSet
и проверьте, присутствует ли этот объект или нет.Будет напечатано следующее:
Теперь раскомментируйте
hashcode()
метод, выполните то же самое, и результат будет:Теперь вы можете понять, почему, если два объекта считаются равными, их хэш-коды также должны быть равны? В противном случае вы никогда не сможете найти объект, поскольку метод хеш-кода по умолчанию в классе Object практически всегда предлагает уникальный номер для каждого объекта, даже если
equals()
метод переопределен таким образом, что два или более объектов считаются равными. , Не имеет значения, насколько равны объекты, если их хэш-коды не отражают это. Итак, еще раз: если два объекта равны, их хэш-код s также должен быть равен.источник
Определив
equals()
иhashCode()
последовательно, вы можете улучшить удобство использования ваших классов в качестве ключей в основанных на хэше коллекциях. Как объясняет документ API для hashCode: «Этот метод поддерживается для использования хеш-таблиц, таких как предоставляемые»java.util.Hashtable
.Лучший ответ на ваш вопрос о том, как эффективно реализовать эти методы, - это прочитать главу 3 « Эффективной Java» .
источник
hashCode()
.Проще говоря, метод equals в Object проверяет равенство ссылок, когда два экземпляра вашего класса могут быть семантически равными, когда свойства равны. Это, например, важно, когда вы помещаете ваши объекты в контейнер, который использует equals и hashcode, такие как HashMap и Set . Допустим, у нас есть такой класс:
Мы создаем два экземпляра с одинаковым идентификатором :
Без переопределения равных мы получаем:
Правильный? Ну, может быть, если это то, что вы хотите. Но допустим, что мы хотим, чтобы объекты с одинаковым идентификатором были одним и тем же объектом, независимо от того, являются ли они двумя разными экземплярами. Мы переопределяем равенства (и хэш-код):
Что касается реализации равенства и хэш-кода, я могу порекомендовать использовать вспомогательные методы Guava.
источник
Личность не равенство.
==
тождеству теста .equals(Object obj)
метод сравнивает тест на равенство (т.е. нам нужно определить равенство, переопределив метод)Сначала мы должны понять использование метода равных.
Чтобы идентифицировать различия между двумя объектами, нам нужно переопределить метод equals.
Например:
Теперь метод hashCode может легко понять.
hashCode создает целое число для хранения объекта в структурах данных, таких как HashMap , HashSet .
Предположим, у нас есть метод переопределения равно
Customer
как выше,При работе со структурой данных, когда мы храним объект в контейнерах (bucket - причудливое имя для папки). Если мы используем встроенную технику хеширования, для более чем двух клиентов она генерирует два разных хеш-кода. Таким образом, мы храним один и тот же объект в двух разных местах. Чтобы избежать подобных проблем, мы должны переопределить метод hashCode, также основанный на следующих принципах.
источник
Хорошо, позвольте мне объяснить концепцию очень простыми словами.
Во-первых, в более широком плане у нас есть коллекции, и hashmap является одной из структур данных в коллекциях.
Чтобы понять, почему мы должны переопределить метод equals и hashcode, нужно сначала понять, что такое hashmap и что делает.
Хэш-карта - это структура данных, которая хранит пары ключевых значений данных в виде массива. Скажем, [], где каждый элемент в 'a' является парой ключ-значение.
Также каждый индекс в вышеуказанном массиве может быть связанным списком, таким образом, имея более одного значения в одном индексе.
Теперь, почему используется hashmap? Если нам нужно искать среди большого массива, тогда поиск по каждому из них, если они не будут эффективными, так что метод хэша говорит нам, что позволяет предварительно обрабатывать массив с некоторой логикой и группировать элементы на основе этой логики, т.е. хеширования
Например: у нас есть массив 1,2,3,4,5,6,7,8,9,10,11, и мы применяем хеш-функцию mod 10, поэтому 1,11 будут сгруппированы вместе. Поэтому, если бы нам пришлось искать 11 в предыдущем массиве, нам пришлось бы выполнять итерацию всего массива, но когда мы группируем его, мы ограничиваем область итерации, тем самым повышая скорость. Эту структуру данных, используемую для хранения всей вышеупомянутой информации, для простоты можно рассматривать как двумерный массив.
Теперь помимо вышеприведенного хэш-карты также говорится, что он не будет добавлять в него никаких дубликатов. И это главная причина, почему мы должны переопределить равенства и хэш-код
Поэтому, когда говорят, что объясняют внутреннюю работу hashmap, нам нужно найти, какие методы имеет hashmap и как он следует вышеприведенным правилам, которые я объяснил выше.
поэтому в hashmap есть метод, называемый как put (K, V), и согласно hashmap он должен следовать приведенным выше правилам эффективного распределения массива и не добавлять дубликаты.
так что дело в том, что он сначала сгенерирует хеш-код для данного ключа, чтобы решить, в какой индекс должно входить значение. Если в этом индексе ничего нет, тогда новое значение будет добавлено туда, если что-то там уже присутствует затем новое значение должно быть добавлено после конца связанного списка в этом индексе. но помните, что дубликаты не должны добавляться в соответствии с желаемым поведением хэш-карты. Допустим, у вас есть два объекта Integer aa = 11, bb = 11. Так как каждый объект является производным от класса объекта, реализация по умолчанию для сравнения двух объектов состоит в том, что он сравнивает ссылку, а не значения внутри объекта. Таким образом, в вышеприведенном случае оба, хотя и семантически равные, не пройдут проверку на равенство, и вероятность того, что два объекта с одинаковым хеш-кодом и одинаковыми значениями будут существовать, создаст дубликаты. Если мы переопределим, мы могли бы избежать добавления дубликатов. Вы также можете сослаться наДетальная работа
источник
hashCode()
:Если вы переопределите только метод хеш-кода, ничего не произойдет. Потому что он всегда возвращает новый
hashCode
для каждого объекта как класс объекта.equals()
:Если вы переопределяете только метод равным, значение
a.equals(b)
true, это означает, чтоhashCode
a и b должны быть одинаковыми, но их не должно быть. Потому что вы не переопределяетеhashCode
метод.Примечание:
hashCode()
метод класса Object всегда возвращает новыйhashCode
для каждого объекта.Поэтому, когда вам нужно использовать ваш объект в коллекции на основе хеширования, необходимо переопределить
equals()
иhashCode()
.источник
Java ставит правило, которое
Итак, если в нашем классе мы переопределим,
equals()
мы должны переопределитьhashcode()
метод также, чтобы следовать этому правилу. Оба метода,equals()
иhashcode()
, используютсяHashtable
, например, для хранения значений в виде пар ключ-значение. Если мы переопределим одно, а не другое, есть вероятность, что онHashtable
может работать не так, как мы хотим, если мы используем такой объект в качестве ключа.источник
Потому что, если вы не переопределите их, вы будете использовать имплантацию по умолчанию в Object.
Учитывая, что равенство экземпляров и значения hascode обычно требуют знания того, из чего состоит объект, они, как правило, должны быть переопределены в вашем классе, чтобы иметь какое-либо ощутимое значение.
источник
Чтобы использовать наши собственные объекты класса в качестве ключей в коллекциях, таких как HashMap, Hashtable и т. Д., Мы должны переопределить оба метода (hashCode () и equals ()), имея представление о внутренней работе коллекции. В противном случае это приведет к неверным результатам, которых мы не ожидаем.
источник
Добавление к ответу @Lombo
Когда вам нужно будет переопределить equals ()?
Реализация по умолчанию Object's equals ()
это означает, что два объекта будут считаться равными только в том случае, если они имеют одинаковый адрес памяти, что будет истинно, только если вы сравниваете объект с самим собой.
Но вы можете рассмотреть два объекта одинаково, если они имеют одинаковое значение для одного или нескольких своих свойств (см. Пример, приведенный в ответе @Lombo).
Таким образом, вы будете переопределять
equals()
в этих ситуациях, и вы дадите свои условия для равенства.Я успешно реализовал equals (), и он работает отлично. Так почему же они просят переопределить hashCode ()?
Хорошо. Пока вы не используете коллекции, основанные на хеше, в вашем пользовательском классе, это нормально. Но когда-нибудь в будущем вы захотите использовать
HashMap
или,HashSet
и если вы не сделаетеoverride
и «правильно реализуете» hashCode () , эта коллекция на основе хэша не будет работать так, как задумано.Переопределить только равно (дополнение к ответу @Lombo)
Прежде всего, HashMap проверяет , является ли хэш - код из
second
такой же , какfirst
. Только если значения совпадают, он будет проверять равенство в том же сегменте.Но здесь hashCode отличается для этих двух объектов (потому что они имеют разные адреса памяти - от реализации по умолчанию). Следовательно, он даже не будет заботиться о равенстве.
Если у вас есть точка останова внутри вашего переопределенного метода equals (), он не будет вмешиваться, если у них разные hashCodes.
contains()
проверяет,hashCode()
и только если они одинаковы, он будет вызывать вашequals()
метод.Почему мы не можем проверить HashMap на равенство во всех сегментах? Поэтому мне не нужно переопределять hashCode () !!
Тогда вы упускаете смысл коллекций, основанных на хеше. Учтите следующее:
Ниже приведены ключи, хранящиеся в виде ведер.
Скажем, вы хотите знать, содержит ли карта ключ 10. Хотели бы вы искать все корзины? или вы хотите искать только одно ведро?
Основываясь на хэш-коде, вы должны определить, что если присутствует 10, он должен присутствовать в сегменте 1. Поэтому будет выполняться поиск только в сегменте 1 !!
источник
hashCode()
для определения сегмента, и используетequals()
метод, чтобы ли это значение в сегменте. Если нет, он будет добавлен, в противном случае он будет заменен текущим значением.hashCode()
сначалаequals()
для поиска Entry (bucket) и для поиска значения в Entryесли оба переопределены,
Карта < >
если равно не переопределено
Карта < >
Если hashCode не переопределен
Карта < >
HashCode Равный Контракт
источник
Рассмотрим коллекцию шариков в ведре в черном цвете. Ваша работа состоит в том, чтобы раскрасить эти шары следующим образом и использовать их для соответствующей игры,
Для тенниса - желтый, красный. Для крикета - белый
Теперь в ведре есть шарики трех цветов: желтый, красный и белый. И что теперь вы сделали раскраску? Только вы знаете, какой цвет для какой игры.
Окраска шаров - хеширование. Выбор мяча для игры - Равно.
Если вы сделали раскраску, и кто-то выбрал мяч для игры в крикет или теннис, они не будут против цвета !!!
источник
Я искал объяснение: «Если вы переопределяете только hashCode, то при вызове
myMap.put(first,someValue)
он берет сначала, вычисляет его hashCode и сохраняет его в данном сегменте. Затем, когда вы вызываетеmyMap.put(first,someOtherValue)
его следует заменить первым на второй в соответствии с документацией карты, потому что они равны (согласно нашему определению). " :Я думаю, что во второй раз, когда мы добавляем,
myMap
это должен быть «второй» объект, какmyMap.put(second,someOtherValue)
источник
1) Распространенная ошибка показана в примере ниже.
Зеленый Автомобиль не найден
2. Проблема, вызванная hashCode ()
Проблема вызвана не переопределенным методом
hashCode()
. Договор междуequals()
иhashCode()
является:Если два объекта имеют одинаковый хэш-код, они могут быть равны или не совпадать.
источник
Это полезно при использовании объектов значения . Ниже приводится выдержка из репозитория шаблонов Portland :
источник
Предположим, у вас есть класс (A), который объединяет два других (B) (C), и вам нужно хранить экземпляры (A) внутри хеш-таблицы. Реализация по умолчанию позволяет различать только экземпляры, но не по (B) и (C). Таким образом, два экземпляра A могут быть равны, но по умолчанию не позволит вам сравнить их правильно.
источник
Методы equals и hashcode определены в классе объекта. По умолчанию, если метод equals возвращает true, тогда система пойдет дальше и проверит значение хеш-кода. Если хеш-код двух объектов также одинаков только тогда, объекты будут считаться одинаковыми. Таким образом, если вы переопределяете только метод equals, тогда, хотя переопределенный метод equals указывает 2 объекта, которые должны быть равны, определенный системой хэш-код может не указывать, что 2 объекта равны. Поэтому нам также необходимо переопределить хеш-код.
источник
true
кequals
не будут рассматриваться как соответствие. С другой стороны, если коллекции происходят, обратите внимание, что вещи не могут иметь одинаковый хэш-код, они, вероятно, не заметят, что они равны.Методы Equals и Hashcode в Java
Это методы класса java.lang.Object, который является суперклассом всех классов (в том числе пользовательских классов и других, определенных в java API).
Реализация:
public boolean equals (Object obj)
Этот метод просто проверяет, ссылаются ли две ссылки на объекты на x и y на один и тот же объект. т.е. проверяет, если х == у.
Это рефлексивно: для любого ссылочного значения x, x.equals (x) должен возвращать true.
Это симметрично: для любых ссылочных значений x и y x.equals (y) должен возвращать true тогда и только тогда, когда y.equals (x) возвращает true.
Это транзитивно: для любых ссылочных значений x, y и z, если x.equals (y) возвращает true и y.equals (z) возвращает true, тогда x.equals (z) должен возвращать true.
Это согласуется: для любых ссылочных значений x и y множественные вызовы x.equals (y) последовательно возвращают true или последовательно возвращают false при условии, что никакая информация, используемая в сравнениях сравнения на объекте, не изменяется.
public int hashCode ()
Этот метод возвращает значение хеш-кода для объекта, для которого этот метод вызывается. Этот метод возвращает значение хэш-кода в виде целого числа и поддерживается для использования классов коллекции на основе хеширования, таких как Hashtable, HashMap, HashSet и т. Д. Этот метод должен быть переопределен в каждом классе, который переопределяет метод equals.
Генеральный договор hashCode:
Всякий раз, когда он вызывается для одного и того же объекта более одного раза во время выполнения приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число при условии, что никакая информация, используемая в сравнениях сравнения для объекта, не изменяется.
Это целое число не должно оставаться согласованным при выполнении одного приложения другим исполнением того же приложения.
Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен привести к одному и тому же целочисленному результату.
Не требуется, чтобы, если два объекта были неравны в соответствии с методом equals (java.lang.Object), то вызов метода hashCode для каждого из двух объектов должен давать разные целочисленные результаты. Тем не менее, программист должен знать, что выдача различных целочисленных результатов для неравных объектов может улучшить производительность хеш-таблиц.
Ресурсы:
Javaranch
Рисунок
источник
В приведенном ниже примере, если вы закомментируете переопределение для equals или hashcode в классе Person, этот код не сможет найти порядок Тома. Использование реализации хеш-кода по умолчанию может вызвать сбои в поисках хеш-таблицы.
Ниже приведен упрощенный код, который определяет порядок людей. Person используется в качестве ключа в хеш-таблице.
источник
Класс String и классы-оболочки имеют различную реализацию
equals()
иhashCode()
методы, чем класс Object. Метод equals () класса Object сравнивает ссылки объектов, а не их содержимое. Метод hashCode () класса Object возвращает отдельный хеш-код для каждого отдельного объекта, независимо от того, является ли содержимое одинаковым.Это приводит к проблемам, когда вы используете коллекцию карт, а ключ имеет тип Persistent, StringBuffer / тип компоновщика. Поскольку они не переопределяют equals () и hashCode () в отличие от класса String, equals () вернет false, когда вы сравниваете два разных объекта, даже если оба имеют одинаковое содержимое. Это сделает хэш-карту, хранящую те же ключи содержимого. Хранение одних и тех же ключей содержимого означает, что оно нарушает правило Map, поскольку Map вообще не допускает дублирование ключей. Поэтому вы переопределяете методы equals (), а также hashCode () в своем классе и предоставляете реализацию (IDE может генерировать эти методы), чтобы они работали так же, как String equals () и hashCode (), и предотвращали одинаковые ключи содержимого.
Вы должны переопределить метод hashCode () вместе с equals (), потому что equals () работает в соответствии с hashcode.
Более того, переопределение метода hashCode () вместе с equals () помогает исправить контракт equals () - hashCode (): «Если два объекта равны, то они должны иметь одинаковый хэш-код».
Когда вам нужно написать собственную реализацию для hashCode ()?
Как известно, внутренняя работа HashMap основана на принципе хеширования. Есть определенные области, где хранятся наборы записей. Вы настраиваете реализацию hashCode () в соответствии с вашими требованиями, чтобы объекты одной категории могли быть сохранены в одном индексе. когда вы сохраняете значения в коллекцию Map с использованием
put(k,v)
метода, внутренняя реализация put () выглядит так:Значит, он генерирует индекс, а индекс генерируется на основе хеш-кода конкретного ключевого объекта. Поэтому заставьте этот метод генерировать хеш-код в соответствии с вашими требованиями, потому что одни и те же наборы записей хеш-кода будут храниться в том же сегменте или индексе.
Это оно!
источник
hashCode()
Метод используется для получения уникального целого числа для данного объекта. Это целое число используется для определения местоположения сегмента, когда этот объект должен быть сохранен в некоторойHashTable
,HashMap
например, структуре данных. По умолчаниюhashCode()
метод Object возвращает целочисленное представление адреса памяти, где хранится объект.hashCode()
Метод объектов используется , когда мы вставляем их вHashTable
,HashMap
илиHashSet
. Больше оHashTables
Wikipedia.org для справки.Чтобы вставить любую запись в структуру данных карты, нам нужны ключ и значение. Если и ключ, и значения являются определяемыми пользователем типами данных,
hashCode()
ключ будет определять, где хранить объект внутри. Когда требуется поиск объекта на карте, хеш-код ключа будет определять, где искать объект.Внутренний хеш-код указывает только на определенную «область» (или список, область и т. Д.). Поскольку разные ключевые объекты потенциально могут иметь один и тот же хеш-код, сам хеш-код не является гарантией того, что правильный ключ найден. Затем
HashTable
он выполняет итерацию этой области (все ключи с одинаковым хеш-кодом) и использует метод ключа,equals()
чтобы найти правильный ключ. Как только правильный ключ найден, объект, сохраненный для этого ключа, возвращается.Итак, как мы видим, сочетание этих
hashCode()
иequals()
методов используется при хранении и при поиске объектов вHashTable
.НОТЫ:
Всегда используйте одни и те же атрибуты объекта для генерации
hashCode()
и то иequals()
другое. Как и в нашем случае, мы использовали идентификатор сотрудника.equals()
должен быть непротиворечивым (если объекты не изменены, то он должен продолжать возвращать одно и то же значение).Всякий раз
a.equals(b)
, тогдаa.hashCode()
должно быть так же, какb.hashCode()
.Если вы переопределяете одно, то вы должны переопределить другое.
http://parameshk.blogspot.in/2014/10/examples-of-comparable-comporator.html
источник
hashCode()
не используется для возврата уникального целого числа для каждого объекта. Это невозможно. Вы сами опровергли это во втором предложении четвертого абзаца.ИМХО, это согласно правилу гласит: «Если два объекта равны, то они должны иметь одинаковый хэш, т. Е. Равные объекты должны создавать одинаковые значения хеша.
Учитывая выше, по умолчанию equals () в Object is ==, который выполняет сравнение по адресу, hashCode () возвращает адрес в целочисленном виде (хэш по фактическому адресу), который снова различен для отдельного объекта.
Если вам нужно использовать пользовательские объекты в коллекциях на основе хэша, вам необходимо переопределить и equals (), и hashCode (), например, если я хочу сохранить HashSet объектов Employee, если я не использую более сильный hashCode и равно Я могу переопределить два разных объекта Employee, это происходит, когда я использую age в качестве hashCode (), однако я должен использовать уникальное значение, которое может быть идентификатором Employee ID.
источник
Чтобы помочь вам найти дубликаты Объектов, нам нужен пользовательский метод equals и hashCode.
Поскольку хэш-код всегда возвращает число, всегда можно быстро получить объект, используя номер, а не алфавитный ключ. Как это будет сделано? Предположим, мы создали новый объект, передав некоторое значение, которое уже доступно в каком-то другом объекте. Теперь новый объект будет возвращать то же хеш-значение, что и для другого объекта, поскольку переданное значение такое же. Как только возвращается одно и то же значение хеш-функции, JVM будет каждый раз обращаться к одному и тому же адресу памяти, и если в случае наличия более одного объекта для одного и того же хеш-значения, он будет использовать метод equals () для определения правильного объекта.
источник
Если вы хотите сохранить и извлечь свой пользовательский объект в качестве ключа в Map, тогда вы всегда должны переопределять equals и hashCode в своем пользовательском объекте. Например:
Здесь p1 и p2 будут рассматриваться как только один объект, а
map
размер будет только 1, потому что они равны.источник
Тестовый класс
В Object Class equals (Object obj) используется для сравнения адреса, поэтому, когда в классе Test вы сравниваете два объекта, метод equals дает false, но когда мы переопределяем hashcode (), он может сравнивать содержимое и давать правильный результат.
источник
Если вы переопределяете
equals()
и нетhashcode()
, вы не найдете никаких проблем, если только вы или кто-то другой не используете этот тип класса в хешированной коллекции, напримерHashSet
. Люди до меня ясно объяснили документированную теорию несколько раз, я просто здесь, чтобы привести очень простой пример.Рассмотрим класс, для которого
equals()
нужно что-то настраивать:Теперь рассмотрим этот основной класс:
Это даст следующий результат:
Я доволен результатами. Но если я не переопределю
hashCode()
, это вызовет кошмар, так как объектыRishav
с одинаковым содержимым больше не будут обрабатываться как уникальные, так какhashCode
будут отличаться, как генерируется поведением по умолчанию, вот что будет выводиться:источник
Оба метода определены в классе Object. И оба в своей простейшей реализации. Поэтому, когда вам нужно, вы захотите добавить еще реализацию к этим методам, тогда у вас есть переопределение в вашем классе.
Для Ex: метод equals () в объекте проверяет его равенство только по ссылке. Поэтому, если вам нужно сравнить его состояние, вы можете переопределить его, как это делается в классе String.
источник
Бах - «Вы должны переопределить hashCode () в каждом классе, который переопределяет equals ()».
[Из Эффективной Явы, Джошуа Блох?]
Разве это не неправильно? Переопределение hashCode, вероятно, подразумевает, что вы пишете класс ключа хеша, но переопределение equals определенно этого не делает. Есть много классов, которые не используются в качестве хеш-ключей, но по какой-то другой причине хотят метод тестирования на логическое равенство. Если вы выберете «равно» для него, вам может быть поручено написать реализацию hashCode из-за чрезмерного усердия в применении этого правила. Все, что достигается, - это добавить непроверенный код в кодовую базу, злое ожидание, чтобы запутать кого-то в будущем. Также написание кода, который вам не нужен, является анти-проворным. Это просто неправильно (и созданный идеей, вероятно, будет несовместим с вашими созданными вручную равными).
Конечно, они должны были назначить интерфейс для объектов, написанных для использования в качестве ключей? В любом случае, Object никогда не должен был предоставлять hashCode () и equals () по умолчанию imho. Вероятно, это поощряется многими битыми коллекциями хешей.
Но в любом случае, я думаю, что «правило» написано задом наперед. А пока я буду избегать использования «равно» для методов проверки на равенство :-(
источник