一、前言
我们都知道在使用HashSet时,是不能添加重复数据的。但是,在什么样的情况下会被判断为重复数据呢?
二、HashSet数据存储过程
先回顾HashSet存储结构:哈希表(数组+链表+红黑树)
其实第一个问题非常简单,我们只需要了解HashSet的数据存储过程即可。如下:
1、根据hashCode计算保存的位置,如果位置为空,直接保存,若不为空,进行第二步;
2、再执行equals方法,如果equals为true,则认为是重复,否则形成链表。
三、如何按照自己的需求来防止添加重复数据
解决第二个问题的办法,我们在弄懂了第一个问题之后就不难想到:
因为HashSet在存储数据时,是根据hashcode和equals方法来判断数据是否重复的。
所以,只需要按照自己的需求重写hashCode()和equals()方法即可。
不同的对象生成的hashcode不一定不相同(即:可能相同);
相同的对象生成的hashcode一定相同。
所以,先比较hashcode,如果hashcode不相同,那么一定是不同的对象;
如果hashcode相同,此时有两种情况:不同的对象得到相同的hashcode,统一对象的hashcode。
因此,重写hashCode()方法和equals()方法即可满足要求。
四、案例
(一)需求
有一个Person类,该类有name和age两个属性。希望在将该类对象添加到HashSet集合中时,根据name和age属性来判断要添加的对象是否已经存在于HashSet集合中。
(二)重写前
1 | public class Person { |
1 | public class Demo { |
测试结果如下:
1 | [Person{name='梁朝伟', age=22}, Person{name='林志玲', age=18}, |
我们可以发现,虽然在添加第四条数据之前,set中已经有梁朝伟这个对象,但是依然添加成功了。
这是因为我们没有重写hashcode方法的话,默认计算hashcode值会和对象的地址有关,而这都是四个不同的对象,因此计算出来的hashcode值都是不同的,所以就直接添加进去了。
因此,如果要实现需求,就必须重写方法。
(三)重写后
1 | public class Person { |
还是相同的测试代码,运行结果如下:
1 | [Person{name='刘德华', age=20}, Person{name='林志玲', age=18}, Person{name='梁朝伟', age=22}] |
因此,通过该案例我们就能发现:如果想要按照内容来判断数据是否重复,只需要重写hashCode()和equals()方法即可。
Java新手,若有错误,欢迎指正!