контракты equals () и hashCode () в Java - PullRequest
7 голосов
/ 05 марта 2011

Учебное пособие SCJP 6 от Берт Бейтс и Кэти Сьерра утверждает на странице 554 (среди прочих требований), что x.hashCode ()! = Y.hashCode () требует, чтобы x.equals (y) == false.

Но в Javadoc for Object такое требование явно не упоминается.Цитата:
Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен привести к одинаковому целочисленному результату.

ЕслиЯ воспринимаю то, что говорит Javadoc, как материальный подтекст, такой как eq -> hc ?Тогда не будет никакого конфликта между этими двумя источниками.

Ответы [ 5 ]

13 голосов
/ 05 марта 2011

Как говорит z5h, операторы эквивалентны.

Для логических условий x и y "x подразумевает y" то же самое, что и "! Y подразумевает! X".

"Есличто-то - это автобус, он красный "логически эквивалентен" если что-то не красный, это не автобус ".

Это противопоставление .

Должен ли я принять то, что Javadoc говорит как материальный подтекст, например, eq -> hc.

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

13 голосов
/ 05 марта 2011

Два утверждения эквивалентны.

Проще говоря:

  1. если два хеш-кода различаются, объекты однозначно различаются при равенстве.
  2. если два хеш-кода совпадают, мы не знаем. (но во многих практических случаях объекты будут равны).
6 голосов
/ 05 марта 2011

Между этими утверждениями нет конфликта, они эквивалентны.

p: x.equals(y)
q: x.hashCode() == y.hashCode()
p implies q
not q implies not p
2 голосов
/ 12 марта 2014

Основные факты о HashMap.
1. HashMap будет генерировать хеш-код для каждого ключа независимо от типа объекта.
2. Если быть точным - хеш-код будет сгенерирован на основе ключа изначение (то есть запись)

Эксперимент: Рассмотрим определяемый пользователем объект (например, SPObject), который является ключом для хэш-карты;SPObject содержит только один параметр ( name ).См .: http://www.programcreek.com/2011/07/java-equals-and-hashcode-contract/

Если hashCode () и equals () не записаны должным образом в классе SPObject, проблемы следующие.
Поместите 2 записи - новый SPObject ("SP") и новый SPObject( "SP").Они рассматриваются как разные объекты и успешно сохраняются в карте.

map.get (новый SPObject ("SP")) вернет ноль.
map.contains (новый SPObject ("SP")) вернет false.

Это результат, если контракт hashCode / equals не обрабатывается должным образом.

<b>hashCode()     |    equals()    | Treated as | Description</b>
No             |      No        | Duplicate  | Stored in different buckets.
                                             | Treated as different object.

Yes            |      No        | Duplicate  | Stored in same bucket.
                                             | Treated as different object. 
                                             | Because, the default(Object) equals method will check only the reference of objects.     

No             |      Yes       | Duplicate  | Stored in different buckets.Treated as different object

Yes(hashlogic) |      Yes       | Unique     | Stored in same bucket.Treated as same object.Efficient.

Yes(constant)  |      Yes       | Unique     | Stored in same bucket.Treated as same object.
                                             | Inefficient, because it will iterate bucket elements for equality check.

0 голосов
/ 12 марта 2014

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

Оба приведенных «требования» относительно hashCode и их равных включают неустановленныепредпосылка: в случаях, когда X.equals(Y) сообщает об истинности, не нужно, чтобы сущности неправильно предполагали, что это ложно.В целом, для кода очень плохо действовать на основе ложных предположений, поэтому разумно предположить, что не нужно, чтобы объекты делали неверные предположения о равенстве объектов.В Учебном руководстве приводятся ссылки на тот факт, что если два объекта имеют неравные хэш-коды, они будут считаться неравными;для того, чтобы такое предположение соответствовало действительности, требуется, чтобы они были неравными.JavaDoc по существу намекает на тот факт, что если два объекта равны, и один хочет избежать того, чтобы сущности предполагали, что они не будут, и не замечает, что они есть, нужно убедиться, что значение hashCode, возвращаемое одним, также будетвозвращается другим.

...