16 两个对象值相同(x.equals(y) == true),但却可以有不同的hashCode,这句话对不对?

不对,如果两个对象x和y满足x.equals(y) == true,那么他们的哈希码应该相同。

根据hashCode方法协定:在每个重写了equals方法的类中,必须重写hashCode方法,如果不这样做的话,就会导致该类无法与基于哈希表的集合一起使用。

接下来我们以HashSet为例说明:

HashSet基于HashMap实现,底层采用HashMap保存元素,元素无序、不重复。

当向HashSet添加元素a时,首先调用a所属类的hashCode方法,计算a的哈希值,接着利用hash值通过某种算法计算出元素在HashSet底层数组中的存放位置;

判断此位置上是否有元素:如果没有,则a添加成功;如果有,假设存在元素b,则先比较a和b的哈希值;

如果哈希值不同,则a添加成功;如果哈希值相同,则继续通过调用a所属类的equals方法比较;

如果返回true,a添加失败;如果返回false,a添加成功。

分析:

以上就是集合HashSet的简要说明及实现原理,假设我们新建一个类Student,重写了equals方法(只要name相等即为true),没有重写hashCode方法,当new了两个相同name的对象stu1,stu2后,分别添加到HashSet中,首先stu1经过hashCode方法,计算哈希值,然后找到自己在数组中的存放位置,发现没有元素,添加成功;接着stu2也调用hashCode方法,但是由于没有重写hashCode方法,返回了不同的哈希值,经过计算也找到了自己在数组中要存放的位置,且该位置和stu1的不同,也添加成功,这就发生了错误,因为我们知道HashSet是不可重复的集合。

结语:

当然,如果你的类根本就不会和基于哈希表的集合一起使用,如ArrayList,你也可以不重写hashCode方法,但是,这就像是Java的一种约定,我们最好遵守它。

原文地址:https://www.cnblogs.com/xilichenbokeyuan/p/14167555.html