2012-03-22 3 views
2

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

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

Под «детерминированным» подразумевается «правильный»? –

+0

В этом случае это не имеет значения, потому что это тот же объект, не так ли? Таким образом, пока 2 вызова на одном и том же объекте производят один и тот же хэш-код, это должно возвращать true. Но да, это тоже правильно. –

+1

Но «детерминированный» не означает «2 вызова на одном и том же объекте производят один и тот же хэш-код». Нет ничего * недетерминированного * о 'ArrayList .hashCode', но см. Мой ответ ... –

ответ

7

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

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

+0

yep, мутация. Благодарю. –

2

Это не ясно, что вы имеете в виду под «детерминированный», но любой хэш-изменение мутации к ключу после того как она вставлена ​​в хэш-карта может легко иметь такой эффект.

import java.util.*; 

public class Test { 
    public static void main(String[] args) { 
    List<String> strings = new ArrayList<String>(); 
    Map<List<String>, String> map = new LinkedHashMap<List<String>, String>(); 

    map.put(strings, ""); 
    System.out.println(map.containsKey(map.keySet().iterator().next())); // true 
    strings.add("Foo"); 
    System.out.println(map.containsKey(map.keySet().iterator().next())); // false 
    } 
} 

Хэш код ArrayList<T> является детерминированным, но это не означает, что она не изменится, если содержимое изменений списка.

1

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

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

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

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

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

+0

нет нитей .. –

+1

не имеет значения, не влияет ли ваш конкретный экземпляр, который вы думаете, не один, а ваш вопрос **, когда это может случиться, это один случай, который может произойти. –

0

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

+0

нет, это есть. Определенно есть элементы. –

3

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

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

0

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

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