2015-10-07 2 views
0

Я знаю, что есть много похожих вопросов, но я не удовлетворен ответами, которые я прочитал. Я попытался понять это, но я до сих пор не понял. Я знаю, что эти два важны при использовании наборов или карт, особенно HashSet, HashMap или Hash-объектов вообще, которые используют хеш-механизм для хранения объектов-элементов.В чем заключается недостаток переопределения равных, а не хэш-код и наоборот?

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

То, что я не понимаю, ПОЧЕМУ, необходимо переопределить оба этих метода. ЧТО, если мы не переопределяем hashcode. ЭТО ДОЛЖНО ПЕРЕСМОТРЕТЬ ОБА. Если это не то, что является недостатком переопределения равных, а не хэш-кода и наоборот.

+2

Вы посмотрели [Какие проблемы следует учитывать при переопределении равных и hashCode в Java?] (Http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals- и-хэш-в-Java/27609 # 27609). Вообще говоря, существует контрактное требование, чтобы любой объект, который является «равным», также создает один и тот же «hashcode» – MadProgrammer

ответ

0

Да, это правильно, когда вы переопределяете метод equals, вам также необходимо переопределить метод hashcode. Причина в том, что в хэш-базовых элементах два объекта равны, если их метод equals возвращает true, а метод hashcode возвращает одно целое значение. В хэш-базовых элементах (хэш-карте), когда вы делаете равную проверку для двух объектов, сначала вызывается метод их хэш-кода, если он возвращает одно и то же значение для метода then only equals. Если hashcode не возвращает одинаковое значение для обоих, тогда простота рассматривает оба объекта как не равные. По умолчанию метод hashcode возвращает некоторое случайное значение, поэтому, если вы делаете два объекта равными для некоторого определенного условия, переопределяя метод equals, они все равно не будут равны, потому что их значение hashcode отличается, поэтому, чтобы сделать их значение hascode равным вам должны переопределить его. В противном случае вы не сможете сделать этот объект ключом вашей хэш-карты.

+0

. Я не уверен, что вы называете «равным чеком»? hashCode имеет значение только в контейнерах на основе хэша: например, HashMap.put (ключ, значение) вычисляет хэш ключа, а затем сравнивает его для .equals() с другими ключами, которые имеют одинаковый хеш, поэтому важно, чтобы эти методы должны быть последовательными. Но объект, который не реализует hashCode, будет отлично работать, скажем, в TreeMap (в этом случае он должен правильно реализовать compareTo, хотя). – jkff

+0

@proudandhonour Похоже, если я переопределяю равный, а не хэш-код, это означает, что я рискую определить два объекта, которые должны быть равны, как не равные? –

+0

Да, когда вы делаете хэш на равных. Пример. Если вы делаете свой объект в качестве ключа к HashMap, и вы переопределяете равный метод, а не метод hashcode, вы никогда не найдете свой объект на карте до тех пор, пока объект, который вы ищете, и ключ на карте не будут одинаковыми одинаковое расположение памяти в JVM). – proudandhonour

1

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

Вот почему это важно для хэш на основе контейнеров, таких как HashMap, HashSet, ConcurrentHashMap и т.д.

На высоком уровне, HashMap массив, индексированный по хэш-код ключа, элементы которого являются " цепочки "- списки пар (ключ, значение), где все ключи в определенной цепочке имеют одинаковый хэш-код. Для обновления хэш-таблиц см. Wikipedia.

Рассмотрите, что произойдет, если два ключа A, B равны, но имеют другой хэш-код - например, a.hashCode() == 42 и b.hashCode() == 37. Предположим, вы пишете:

hashTable.put(a, "foo"); 
hashTable.get(b); 

Поскольку ключи равны, вы хотели бы, чтобы результат "foo", верно? Однако get(b) рассмотрит цепочку, соответствующую хешу 37, в то время как пара (a, "foo") находится в цепочке, соответствующей хешу 42, поэтому поиск не удастся, и вы получите null.

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

Обратите внимание, что если вы используете контейнер, не содержащий хэш, например TreeMap, тогда вам не нужно реализовывать hashCode, потому что контейнер его не использует. Вместо этого, в случае TreeMap, вы должны реализовать compareTo - другие типы контейнеров могут иметь свои собственные требования.

+0

, который очищает мое сомнение. большое спасибо –

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