equals() 判断两对象是否相等,hashCode() 计算对象哈希码
都不是 final 方法,都可被重写
使用和重写时,注意
Object 的equals()
|
|
Object 实现区分度最高,两对象不是同一个对象, 一定返回 false
equals() 应遵守约定
-
自反:x.equals(x) 必须 true
-
对称:x.equals(y) 与 y.equals(x) 要相等
-
传递:x.equals(y) true,y.equals(z) true,x.equals(z) 必须 true
-
一致:x 和 y 在 equals() 中使用的信息都没有改变,x.equals(y) 值要始终不变
-
非 null:x 不是 null,y 为 null,x.equals(y) 必须 false
Object 的 hashcode()
|
|
将对象内存地址作哈希码返回,保证不同对象返回值不同
-
哈希表中起作用
-
如果对象在 equals() 中使用的信息都没有改变,那么 hashCode() 值始终不变
-
如果两个对象使用 equals() 方法判断为相等,则 hashCode() 方法也应该相等
-
如果两个对象使用 equals() 方法判断为不相等,则不要求 hashCode() 也必须不相等;但是开发人员应该认识到,不相等的对象产生不相同的 hashCode 可以提高哈希表的性能
为什么要 hashCode()
插入时通过哈希码直接映射到哈希表中的位置
-
该位置没有对象,直接插入该位置
-
该位置有对象,调 equals() 比较对象是否相等,相等则不需保存;不相等,加入到链表中(jdk8优化为达到链表阀值用红黑树提升性能)
解释了为什么 equals() 相等,则 hashCode() 必须相等
equals()相等,哈希表中只出现一次;如 hashCode()不相等,会散列到哈希表不同位置,哈希表中出现了不止一次
String hashCode()
|
|
1、 String 数据是 final 的
|
|
s = “world” 并不是字符串对象的值变为了 “world”,而是新建了一个 String 对象,s 引用指向了新对象
2、 String 类将 hashCode() 的结果缓存为 hash 字段的值,提高性能
3、 String 对象 equals() 相等的条件是二者同为 String 对象,长度相同,且字符串值完全相同;不要求二者是同一个对象
4、 String 的 hashCode() 计算公式为:s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1]
数字 31
-
质数计算哈希码,它与其他数字相乘之后,计算结果唯一的概率更大,哈希冲突的概率更小
-
质数越大,哈希冲突的概率越小,但计算速度也越慢;31 是哈希冲突和性能的折中,经验值
-
JVM 会自动对 31 进行优化:31 * i == (i « 5) - i