这道题也是面试常问得——“你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode ⽅法?”
hashCode()
方法的作⽤是获取哈希码,它会返回⼀个 int 整数,定义在 Object 类open in new window中, 是一个本地⽅法。
public native int hashCode();
hashCode 方法主要用来获取对象的哈希码,哈希码是由对象的内存地址或者对象的属性计算出来的,它是⼀个 int 类型的整数,通常是不会重复的,因此可以用来作为键值对的建,以提高查询效率。
例如 HashMapopen in new window 中的 key 就是通过 hashCode 来实现的,通过调用 hashCode 方法获取键的哈希码,并将其与右移 16 位的哈希码进行异或运算。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
维护 equals()
和 hashCode()
之间的一致性是至关重要的,因为基于哈希的集合类(如 HashSet、HashMap、Hashtable 等)依赖于这一点来正确存储和检索对象。
具体地说,这些集合通过对象的哈希码将其存储在不同的“桶”中(底层数据结构是数组,哈希码用来确定下标),当查找对象时,它们使用哈希码确定在哪个桶中搜索,然后通过 equals()
方法在桶中找到正确的对象。
如果重写了 equals()
方法而没有重写 hashCode()
方法,那么被认为相等的对象可能会有不同的哈希码,从而导致无法在集合中正确处理这些对象。
这主要是由于哈希码(hashCode)的本质和目的所决定的。
哈希码是通过哈希函数将对象中映射成一个整数值,其主要目的是在哈希表中快速定位对象的存储位置。
由于哈希函数将一个较大的输入域映射到一个较小的输出域,不同的输入值(即不同的对象)可能会产生相同的输出值(即相同的哈希码)。
这种情况被称为哈希冲突。当两个不相等的对象发生哈希冲突时,它们会有相同的 hashCode。
为了解决哈希冲突的问题,哈希表在处理键时,不仅会比较键对象的哈希码,还会使用 equals 方法来检查键对象是否真正相等。如果两个对象的哈希码相同,但通过 equals 方法比较结果为 false,那么这两个对象就不被视为相等。
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;