Почему существует другая ситуация, когда хэш-код ключа имеет три ситуации больше или меньше или равно? - PullRequest
0 голосов
/ 19 января 2019

В java.util.HashMap.TreeNode#putTreeVal() есть некоторый код, как показано ниже:

if ((ph = p.hash) > h)
    dir = -1;
else if (ph < h)
    dir = 1;
else if ((pk = p.key) == k || (k != null && k.equals(pk)))
    return p;
else if ((kc == null &&
          (kc = comparableClassFor(k)) == null) ||
         (dir = compareComparables(kc, k, pk)) == 0) {
    if (!searched) {
        TreeNode<K,V> q, ch;
        searched = true;
        if (((ch = p.left) != null &&
             (q = ch.find(h, k, kc)) != null) ||
            ((ch = p.right) != null &&
             (q = ch.find(h, k, kc)) != null))
            return q;
    }
    dir = tieBreakOrder(k, pk);
}

Существует две ситуации: h меньше ph, h больше ph. Обычно код (pk = p.key) == k || (k != null && k.equals(pk)) означает h равняется ph, но я не знаю, почему еще после этого.

Какова ситуация, когда hashCode двух объектов равны друг другу, но == и euqlas() получат false?

Когда метод переопределения класса Object equals() вызовет эту ситуацию? Но раньше я слышал, что переопределение equals() тоже должно переопределять hashCode(), так что этот вопрос не возникнет.

Я надеюсь, что некоторые люди могут сказать мне, какая ситуация вызовет третий else if.

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Какова ситуация, когда hashCode двух объектов равен друг другу, но == и equals () получат значение false?

Согласно документации Java:

  • Если объекты равны (т. Е. x.equals(y) == true), то hashCode этих объектов также должны быть равны (т. Е. x.hashCode() == y.hashCode())
  • Если два объекта равны hashCode (т. Е. * 1014)*), тогда не обязательно, чтобы эти объекты были равны (т. е. x.equals(y) == true/false)

См. подробности в Oracle Java Tutorial: Объект как суперкласс

0 голосов
/ 19 января 2019

Какова ситуация, когда hashCode двух объектов равен друг другу, но == и equals () получат false?

Когда происходит коллизия хеш-кода.

Пример

Рассмотрим эти два длинных:

Long l1 = 1L;
Long l2 = 4294967296L; //which is 2 ^ 32

Согласны ли вы с тем, что есть разные и equals() вернет false? Тем не менее, результат

l1.hashCode() == l2.hashCode()

верно.

Почему? Посмотрите на реализацию hashCode для Long:

public static int hashCode(long value) {
    return (int)(value ^ (value >>> 32));
}

Поскольку long может иметь 2 ^ 64 значения, а возвращаемое значение хеш-кода - это int, которое может иметь 2 ^ 32 значения, это нормально, если у вас есть коллизии (каждое значение создает коллизии с 2 ^ 32 другими значениями).


Разъяснения

Но я слышал, что override equals () тоже должно переопределять hashCode (), так что этот вопрос не случится.

Да, когда вы переопределяете equals(), вы должны переопределить также hashCode(). Это правда, но я думаю, что вы перепутали последствия. Из Javadoc хэш-кода :

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

Не требуется, чтобы, если два объекта были неравны метод equals (java.lang.Object), затем вызывается метод hashCode каждый из двух объектов должен давать разные целочисленные результаты. Тем не менее, программист должен знать, что создание различных целочисленные результаты для неравных объектов могут улучшить производительность хеш-таблицы.

Итак, смысл

a.equals(b) => a.hashCode() == b.hashCode()

должно быть всегда верно (если ваши методы реализованы правильно), но обратное значение

a.hashCode() == b.hashCode() => a.equals(b)

не обязательно должен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...