关于重写equals()为什么一定要重写hashcode()自己的一点心得

首先我们看下下面代码及输出和String重写equals和hashcode的源码:

package com.zzy.test;

public class Test6 {
    public static void main(String[] args) {
        String s1="aaa";
        String s2="aaa";
        String s3=new String("aaa");
        String s4="bbb";
        System.out.println(s1.equals(s2));
        System.out.println(s1.hashCode()+"------"+s2.hashCode());
        System.out.println(s1==s2);
        System.out.println("------------------------------------");
        System.out.println(s1.equals(s3));
        System.out.println(s1.hashCode()+"------"+s3.hashCode());
        System.out.println(s1==s3);
        System.out.println("------------------------------------");
        System.out.println(s1.equals(s4));
        System.out.println(s1.hashCode()+"------"+s4.hashCode());
        System.out.println(s1==s4);

    }
}
output:
true
96321------96321
true
------------------------------------
true
96321------96321
false
------------------------------------
false
96321------97314
false

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

在写这块代码的时候惊奇的发现String不用导包,原来java.lang包下的内容都是自动就导入的,我竟然现在才发现这个。
首先我们看下s1和s2的比较,equals比较返回true(因为String重写了Object的equals方法,重写后是判断内容相等,之前是判断内存地址是否一样),hashcode值也相等(两者对象本身就相等,hashcode必然相等),比较地址也相等,因为s1 s2 指向是同一个对象“aaa”,“aaa”在第一次创建后会在常量池中,然后s1和s3的比较,首先两者内容和hashcode相等,但是地址是不一样的,这是因为重写equals的时候也重写了hashcode,而如果equals相等hashcode也必须相等,如果只重写了equals不重写hashcode就会导致可能会出现equals相等,但hsahcode不相等的情况。下面我们可以看下一个自定义类只重写equals方法的情况:

package com.zzy.test;

import com.zzy.bean.Person;

public class Test7 {
    public static void main(String[] args) {
        Person person1 = new Person("张三", 18);
        Person person2 = new Person("张三", 18);
        System.out.println(person1.equals(person2));
        System.out.println(person1.hashCode()+"------"+person2.hashCode());
        System.out.println(person1==person2);
    }
}
//不重写equals和hashcode时output:
false
2125039532------312714112
false
//只重写equals时output:
true
2125039532------312714112
false
//两者都重写时output:
true
24022538------24022538
false

可以很清楚看出三种情况的区别,有的人可能会问为什么equals相等要保证hashcode相等呢
如果内容相等而hashcode不等,在使用散列数据结构(HashSet,HashMap,LinkedHashSet或LinkedHashMap)时就会出现问题,由于散列表中桶位的下标是hashcode经过一些处理以及根据容器的程度和负载因子来生成的,这样就会导致插入两个内容相同的key可能会出现不覆盖的情况,代码举例如下:

package com.zzy.test;

import com.zzy.bean.Person;

import java.util.HashMap;

public class Test7 {
    public static void main(String[] args) {
        Person person1 = new Person("张三", 18);
        Person person2 = new Person("张三", 18);
        HashMap<Person, Integer> map = new HashMap<Person, Integer>();
        map.put(person1,3);
        System.out.println(map.get(person1));
        map.put(person2,4);
        System.out.println(map.get(person2));
        System.out.println(map.get(person1));
    }
}
//只重写equals时output:
3
4
3
//两者都重写时output:
3
4
4

可以看到只重写equals的时候put两个内容相同的key不会覆盖,两者都重写才会覆盖。这就是为什么要重写equals的时候也要重写hashcode了。

以上就是我关于为什么要重写equals的时候也要重写hashcode的一些心得,大家如果觉得看了对自己有所帮助,还望能点个关注点个赞,感谢

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值