Что происходит, когда Map Java содержит ключ (E e) в Java


я проверил исходный код:

    public boolean containsKey(Object key) {
        Iterator<Map.Entry<K,V>> i = entrySet().iterator();
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return true;
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey())) 
                    return true;
            }
        }
        return false;
    }


 public boolean equals(Object obj) {
        return (this == obj);
    }

Исходя из исходного кода, он показывает, что был вызван только метод "equal ()", поэтому, если я хочу поместить пользовательский объект на карту, я мог бы только переопределить метод "equal ()". так что я сделал эксперимент, результат отрицательный... я должен переопределить оба "equals ()" и "hashCode()" . поэтому мой вопрос:

  1. почему оба метода (equals(),hashCode()) должны быть переопределены.
  2. внутренняя операция "==" вызывает метод "hashCode ()"?

2 ответа

  1. Из API Object.equals: обычно необходимо переопределять метод hashCode всякий раз, когда этот метод переопределяется, чтобы поддерживать общий контракт для метода hashCode, в котором говорится, что равные объекты должны иметь одинаковые хеш-коды. Вы можете найти более подробное объяснение в "Эффективной Java". Элемент 9. Всегда переопределять hashCode, когда вы переопределяете equals.

  2. Нет, нет, это просто сравнение указателей, как сравнение двух целых

Это AbstractMapРеализация. HashMap, который переопределяет это, реализует это следующим образом:

public boolean containsKey(Object key) {
    return getEntry(key) != null;
}

final Entry<K,V> getEntry(Object key) {
    if (size == 0) {
        return null;
    }

    int hash = (key == null) ? 0 : hash(key);
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

final int hash(Object k) {
    int h = hashSeed;
    if (0 != h && k instanceof String) {
        return sun.misc.Hashing.stringHash32((String) k);
    }

    h ^= k.hashCode();

    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

Как видите, это зависит от hashCode(), Другие типы карт могут действительно не зависеть от переопределения этого метода.

Другие вопросы по тегам