hashCode和equals官方注释译文

缘起

hashCode和equals在我们学习javase的伊始就学过了. 但是初学者(例如我)真的不一定去好好读读它的注释. 因为如果没理解HashMap、HashSet、HashTable等哈希系列的集合的源码的话,还真不一定能理解,所以最多为了面试背了一些条条框框. 在【1】的基础上,回头再次阅读注释并给出如下译文.

分析

hashCode方法的源码注释如下

该方法返回对象的hash值,这个值在诸如 HashMap 的哈希表数据结构中有用到.

关于hashCode的约定如下

  1. 一个java进程的执行过程中对同一个对象多次调用hashCode方法得到的值是相同的整数——除非用于equals方法中比较的属性被修改了. 这个整数在不同的java进程中不需要保持一致.
  2. 如果两个对象根据equals方法是相等的,那么hashCode的值也要一样. 但是equals方法不相等的对象不要求他们的hashCode 一定不同. 例如”ABCDEa123abc”和 “ABCDFB123abc”的hashCode都是 165374702。但是程序员必须要清楚——“保持equals不相等的元素的hashcode也不一样”有利于Hash表的性能表现(performance).这个参见【1】的insert算法, 因为这就是在减少哈希碰撞——因为hash值一样但是equals不一样的元素就会进入到链表(或者红黑树)中去. 这至少是HashMap 对哈希碰撞的处理——拉链法(而不是开放地址法,哈希表处理冲突的算法就2种, 1. 拉链 2.开放地址),所以官方推荐保持”equals相等等价于hashcode相等”的写法(虽然不强制)
  3. hashCode方法是native的,而不是java的

equals方法的源码注释如下

用于比较两个对象是否相等. 它是一种等价关系,即满足

  1. 自反性 x.equals(x)返回true,只要x不为null
  2. 对称性 x,和y 非null, 则 x.equals(y)与y.equals(x)的结果是一样的
  3. 传递性,即对于x,y,z三个非null 对象,x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)也必定返回true

最后还有一条性质,就是 x.equals(y)不管你调用几次,只要用于equals比较的属性没有发生变化,结果就保持一致.
在没有被覆写的情况下,x.equals(y)返回true当且仅当x和y指向的是同一块内存地址(即x和y表示的是同一个对象).
注意,equals方法一般是要被覆写的,当然,覆写的时候要注意和hashcode(这个方法也可能覆写)的覆写保持一致,即满足上面hashcode的业界共识第二条. 简言之就是”equals相等=>hashcode相等”

参考

【1】https://yfsyfs.github.io/2019/06/07/java-util-HashMap-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/