当键的哈希码具有大于或小于或等于三个的情况时,为什么还有其他情况?

时间:2019-01-19 09:10:47

标签: java hashmap

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小于phh大于ph。 通常,代码(pk = p.key) == k || (k != null && k.equals(pk))的意思是h等于ph,但是我不知道为什么之后还还有其他内容。

两个对象的hashCode彼此相等,但是==euqlas()变为假时,会发生什么情况?

当Object的类重写equals()方法会导致这种情况吗?但是我以前听说覆盖equals()也必须覆盖hashCode(),所以这个问题不会发生。

我希望有人能告诉我哪种情况会导致第三个else if

2 个答案:

答案 0 :(得分:2)

  

两个对象的hashCode等于每个时的情况是什么   其他,但==和equals()会为假?

根据Java文档:

  • 如果对象相等(即x.equals(y) == true),则这些对象的hashCode也应相等(即x.hashCode() == y.hashCode()
  • 如果两个对象具有相等的hashCode(即x.hashCode() == y.hashCode()),则这些对象不必相等(即x.equals(y) == true/false

查看Oracle Java Tutorial: Object as a Superclass

中的详细信息

答案 1 :(得分:1)

  

当两个对象的hashCode彼此相等,但是==和equals()将变为false时,情况是什么?

发生哈希码冲突时。

示例

考虑这两个Longs:

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

您是否同意存在不同,并且equals()将返回false?但是,

的结果
l1.hashCode() == l2.hashCode()

是真的。

为什么?查看Long的hashCode的实现:

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

由于long可以具有2 ^ 64个值,并且哈希码的返回值是一个可以具有2 ^ 32个值的int值,因此发生冲突是很正常的(每个值都会与其他2 ^ 32个值发生冲突)。 / p>


说明

  

但是我曾经听说重写equals()也必须重写hashCode(),   所以这个问题不会发生。

是的,当您覆盖equals()时,您也应该覆盖hashCode()。的确如此,但我认为您的含意错综复杂。来自javadoc of hashcode

  

如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。

     

如果两个对象根据   equals(java.lang.Object)方法,然后在调用hashCode方法   两个对象中的每一个必须产生不同的整数结果。   但是,程序员应该意识到,   不相等对象的整数结果可能会提高   哈希表。

所以含义

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

必须始终为真(如果正确实现了您的方法),但含义相反

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

不一定必须。