хеш-таблица Java содержит странности - PullRequest
2 голосов
/ 23 марта 2012

При каких обстоятельствах при правильной реализации hashCode и equals () следующий код может вернуть false?

myLinkedHashMap.containsKey(myLinkedHashMap.keySet().iterator().next())

Ответы [ 7 ]

7 голосов
/ 23 марта 2012

Наиболее вероятный сценарий, о котором я могу подумать, будет, даже если hashCode является "детерминированным", он может основываться на изменяемых полях.Если вы измените поля, используемые для вычисления hashCode после того, как он введен в Map, вы больше не сможете его найти.

Редактировать: следует уточнить, что "обычно"смог найти его больше.Иногда это все равно будет работать, так как два числа все еще могут перефразировать в одно и то же ведро.Это, конечно, только добавляет путаницы, когда это происходит!

3 голосов
/ 23 марта 2012

Каждый алгоритм хеширования, который я видел, является «детерминированным», так как для данного набора входных значений вы получаете одно и то же хеш-значение.

Если хеш-код вычисляется на основе изменяемых свойств объектахеш-код изменится после того, как он будет в хеш-карте, если будет изменено какое-либо из этих изменяемых свойств.

2 голосов
/ 23 марта 2012
  1. Если hashCode() основан на атрибутах экземпляра, которые mutable , и эти атрибуты изменены после вставки, вызов hashCode() во время итерации вернет что-то другое.И equals() должен основываться на этих же атрибутах, ожидается, что он также потерпит неудачу.

  2. Когда другой поток удалил все элементы next изMap в середине итерации, больше не будет next().

Я бы не использовал значения hashCode() в качестве ключей, я бы вам сами объекты.

2 голосов
/ 23 марта 2012

Непонятно, что вы подразумеваете под "детерминистическим", но любая изменяющая хэш-мутация ключа после ее вставки в хэш-карту может легко иметь такой эффект.ArrayList<T> является детерминированным, но это не значит, что оно не изменится, если содержимое списка изменится.

1 голос
/ 23 марта 2012

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

Надеюсь, это поможет!

0 голосов
/ 23 марта 2012

Вы можете удалить первый ключ в другом потоке между получением первых ключей и вызовом containsKey.

0 голосов
/ 23 марта 2012

Вы можете сначала проверить hasNext ().

...