使用HashSet 为什么要重写hashcode()和equals() 方法
< 返回列表时间: 2020-06-18来源:OSCHINA
使用HashSet 为什么要重写hashcode()和equals() 方法
Object.hashCode() 和 equals() 方法的用途
hashCode()方法和equals()方法的作用其实一样,在Java里都是用来对比两个对象是否相等一致。
hashcode 其实是对象物理地址返回的整数值,equals() 方法默认比较的就是两个对象的地址是否相同;所以equals() 相等的两个对象,hashCode 一定相同;
下边从两个角度介绍了他们的区别:一个是性能,一个是可靠性。他们之间的主要区别也基本体现在这里。
1、equals()既然已经能实现对比的功能了,为什么还要hashCode()呢?
因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。
2、hashCode()既然效率这么高为什么还要equals()呢?
因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,所以我们可以得出(PS:以下两条结论是重点,很多人面试的时候都说不出来):
equals()相等的两个对象他们的hashCode()肯定相等,也就是用equals()对比是绝对可靠的。
hashCode()相等的两个对象他们的equals()不一定相等,也就是hashCode()不是绝对可靠的。
HashSet 为什么要重写两个方法
HashSet 底层使用HashMap实现的,但是HashSet 有元素不可重复的原则。
如果类并没有重写两个方法,不能保证元素的的不可重复的原则,举例如下:
有一个类User Class User { private int id; private String name; // set get 方法省略 } public void test1() { User user1 = new User(); user1.setId(3); user1.setName("ddd"); User user2 = new User(); user2.setId(3); user2.setName("ddd"); HashSet set = new HashSet(); boolean r1 = set.add(user1); boolean r2 = set.add(user2); System.out.println(r1); System.out.println(r2); }
打印结果: true true
两个对象属性一样,但是依然还是添加进了set 集合,这不符合我们想要的不可重复结果。具体原因看HashMap的put()方法源码。

在判断元素是否已存在的时候: 要先进行当前链表头结点与新增加的节点的hash值判断是否相等。 进行key 值(HashSet的key就是存入对象,value 为Object present 的常量)的equals方法判断。
按照上面User1 和 User2 两个对象,hash值肯定不同,equals 方法比较两个对象的地址,均为false。所以Hashmap 认为两者不是相同的对象,所以都添加成功。这显然不符合我们的实际业务要求。所以我们要重写hashcode 和 equals 方法。只重写一个方法依然不满足。重写举例如下: @Override public int hashCode() { return id; } @Override public boolean equals(Object obj) { obj = (User) obj; return ((User) obj).id == this.id && ((User) obj).name == this.name; }
执行结果: true false
从结果上可以看出,user2没有添加成功,这符合我们的要求。(PS: 这里说明下,HashMap是不会处理重复不重复的,如果重复了直接将原值覆盖,并且将旧值返回,所以user2 从原理上说是覆盖掉了user1,但两个元素一样,所以HashSet 不可重复依然满足,HashSet的添加成功的判断是根据HashMap 的put 有没有返回值判断的,如果有说明旧值被覆盖了,但是提示用户添加失败,这只是从面上看上去是失败而已,其实是成功了。)
hashCode 和equals 方法的重写原则
hashCode和equals 1.只要重写equals,就必须重写hashCode 2.因为Set存储的是不重复的对象(根据hashCode和equals判断),所以Set储存的对象必须重写这两个方法 3.如果自定义对象作为Map的Key,必须重写hashCode和equals
热门排行