覆写equals方法必须覆写hashCode方法
来源:互联网 发布:vb计算机编程基础知识 编辑:程序博客网 时间:2024/06/09 23:44
覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先来看如下代码:
- public static void main(String[] args) {
- // Person类的实例作为Map的key
- Map<Person, Object> map = new HashMap<Person, Object>() {
- {
- put(new Person("张三"), new Object());
- }
- };
- // Person类的实例作为List的元素
- List<Person> list = new ArrayList<Person>() {
- {
- add(new Person("张三"));
- }
- };
- // 列表中是否包含
- boolean b1 = list.contains(new Person("张三"));
- // Map中是否包含
- boolean b2 = map.containsKey(new Person("张三"));
- }
代码中的Person类与上一建议相同,euqals方法完美无缺。在这段代码中,我们在声明时直接调用方法赋值,这其实也是一个内部匿名类的操作(下一个建议会详细说明)。现在的问题是b1和b2这两个boolean值是否都为true?
我们先来看b1,Person类的equals覆写了,不再判断两个地址是否相等,而是根据人员的姓名来判断两个对象是否相等,所以不管我们的new Person(“张三”)产生了多少个对象,它们都是相等的。把“张三”对象放入List中,再检查List中是否包含,那结果肯定是true了。
接着来看b2,我们把张三这个对象作为了Map的键(Key),放进去的对象是张三,检查的对象还是张三,那应该和List的结果相同了,但是很遗憾,结果是false。原因何在呢?
原因就是HashMap的底层处理机制是以数组的方式保存Map条目(Map Entry)的,这其中的关键是这个数组下标的处理机制:依据传入元素hashCode方法的返回值决定其数组的下标,如果该数组位置上已经有了Map条目,且与传入的键值相等则不处理,若不相等则覆盖;如果数组位置没有条目,则插入,并加入到Map条目的链表中。同理,检查键是否存在也是根据哈希码确定位置,然后遍历查找键值的。
接着深入探讨,那对象元素的hashCode方法返回的是什么值呢?它是一个对象的哈希码,是由Object类的本地方法生成的,确保每个对象有一个哈希码(这也是哈希算法的基本要求:任意输入k,通过一定算法f(k),将其转换为非可逆的输出,对于两个输入k1和k2,要求若k1=k2,则必须f(k1)=f(k2),但也允许k1≠k2,f(k1)=f(k2)的情况存在)。
那回到我们的例子上,由于我们没有重写hashCode方法,两个张三对象的hashCode方法返回值(也就是哈希码)肯定是不相同的了,在HashMap的数组中也就找不到对应的Map条目了,于是就返回了false。
问题清楚了,修改也非常简单,重写一下hashCode方法即可,代码如下:
- class Person {
- /*其他代码相同,不再赘述*/
- @Override
- public int hashCode() {
- return new HashCodeBuilder().append(name).toHashCode();
- }
- }
其中HashCodeBuilder是org.apache.commons.lang.builder包下的一个哈希码生成工具,使用起来非常方便,诸位可以直接在项目中集成。(为什么不直接写hashCode方法?因为哈希码的生成有很多种算法,自己写麻烦,事儿又多,所以采用拿来主义是最好的方法。)
- 覆写equals方法必须覆写hashCode方法
- 使用Set集合时,覆写hashCode()和equals()方法
- 如何覆写java中的equals和hashcode方法
- HashSet覆写equals 和hashcode 方法进行类别比较
- 类中equals,hashcode方法的覆写
- equals方法覆写
- 覆写equals方法
- 对象相等判断时,覆写equals方法时同时覆写hashcode方法
- 对象相等判断时,覆写equals方法时同时覆写hashcode方法
- Hibernate中PO的equals()和hashCode()方法的覆写方法
- 为实现非系统类作为Map的key需要覆写hashCode()和equals()方法
- 向HashSet集合存入对象,去除重复元素(覆写equals和hashCode方法)
- Java覆写equeal和hashCode方法
- java对象覆写hashCode equal方法
- hashCode()和equals()的覆写问题
- Java基础回顾:覆写equals()方法
- 为什么覆写equals的时候一定要覆写hashCode?
- 为什么覆写equals的时候一定要覆写hashCode
- 位域/字节对齐
- 关于二叉堆(优先队列)的其他操作及其应用
- #ifdef endef的用法
- centos 6.x x86 源码安装git-2.3.0
- 程序员面试:电话面试问答Top 50
- 覆写equals方法必须覆写hashCode方法
- 宏定义
- 【ASC44E】【构造】Embedding Caterpillars 毛毛虫图向完全图的映射
- java基础知识总结(二)
- Media and Camera 中 Camera 模块
- uva 129 Krypton Factor (DFS+巧妙的判断方法)
- 更改 状态栏(UIStatusBar)的颜色
- jQuery实现点击弹出层3秒后自动消失
- LeetCode 刷题: 两个二叉树节点的最近公共节点Least Common Ancestor