问:重写equals不重写hashCode会怎样?

·  阅读 289

在java中,equals和hashCode方法是Object类的方法,因此,所有用户编写的类都默认拥有这两个方法。

equals方法的作用

根据equals的英文翻译可以看出,这个方法的作用主要是用于比较两个对象是否相等。

在Object类中,equals方法默认使用“==”号来对两个对象进行判断,而在java中,“==”号用在两个对象身上时,比较的是两个对象的地址值,这就意味着当两个对象不是同一个时(地址值不一致就不是同一个对象),就返回为false。

这种判断方式本质上没错,但是不太符合实际需求,就好比在两个不同的超市里面都有矿泉水,但是因为地址值不同,在使用equals做判断时,这两个超市的矿泉水就会返回为false;因此在实际开发中我们往往需要重写Object的equals方法。

hashCode方法的作用

未重写hashCode方法时,它的作用主要是根据当前对象返回一个整型的hash值,不同对象调用hashCode返回的值往往是不一样的。

在java底层集合框架中,为了提高查询效率,往往使用hashCode方法来确定元素的保存位置。

重写equals不重写hashCode会怎样?

以下Sudent类只重写了,Object的equals方法,没有重写hashCode方法\

测试一下:

测试结果:

按照我们的常规理解,只要两个学生对象的id和name是一样的,我们就可以认为这两个学生对象指的是同一个人,因此重写了equals方法,让Student对象只要name和id相同就返回true,而且并没有重写hashCode方法。

在测试中,新建了两个Student对象,并且让他们的id和name完全一样,在调用equals方法时,返回为true,说明这两个对象时相等的。但是由于没有重写hashCode方法,所以这两个对象调用的hashCode还是Object类那里的hashCode方法,并且他们的值并不相等。

由此可以得出结论:重写了equals方法,不重写hashCode方法时,可能会出现equals方法返回为true,而hashCode方法却返回不同的结果。

那么这样会有什么影响呢?

在java底层的集合框架中(如HashMap,HashSet等),为了提高查询的效率,在确定某个对象的存储位置时,往往需要通过调用对象的hashCode方法来实现。

例如在上例中,我们把新建出来的两个Student对象放入HashSet集合中:

按照我们主观理解,这两个对象equals为true,那么HashSet应该主动帮我们去重,最终的HashSet中应该只保留1个对象,即最终输出的HashSet的size为1,但是我们得到的结果却是2:

之所以会产生这种结果,是因为HashSet的底层其实时数组结构,当需要把一个对象放进去时,会先调用这个对象的hashCode方法,并对返回的结果进行处理,最终得出该对象在HashSet中的具体位置。

由于Student没有重写hashCode方法,所以即使equals判断为true,但是他们保存的位置在底层数组上时不一样的,不会触发HashSet的去重功能,而对于程序员来说,两个相同的对象却会在HashSet中出现多次。

分类:
后端
标签:
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改