了解为什么重写equals需要重写hashcode(个人理解)?

了解为什么重写equals需要重写hashcode?

对于 a==b ,如果a,b为基本数据类型,那么会进行值对比,否则会进行对对象地址的对比。而在顶级父类 Object中的equals方法返回为 return(o == this),完全就是对比两个对象的地址是否相等来判断两个对象是否相等。

而因为对象会被保存在堆内存中,即:即使两个新建对象值完全相同,但地址也一定不同。而常量会被保存在常量池中,在新建一个常量之前,会先判断常量池中是否已经有了相同常量,如果有就把相同常量的地址返回给变量。否则就在常量池中新建一个常量再把地址返回给这个变量。
可通过以下代码验证:

		String A = new String("www");
        String B = new String("www");
        String C ="www";
        String D = C;
        String E = "www";
        E=E.substring(0,1);
        System.out.println(A==B);
        System.out.println(A.equals(B));
        System.out.println(A.hashCode());
        System.out.println(B.hashCode());//String 类重写了hashCode()方法
        System.out.println(C.hashCode());
        System.out.println(E.hashCode());
        System.out.println(A==C);
        System.out.println(B==C);
        System.out.println(D==C);
        System.out.println(E==A);
        System.out.println(A);

结果为:
false
true
118167
118167
118167
119
false
false
true
false
www


而那么假设String没有重写equals方法,就会导致两个拥有相同字符串的String对象因为地址不同而导致equals返回为false。这样是因为new String(“www”) != new String(“www”)。而从逻辑上来说,两个包含字符串相同的String对象equals应该返回true。

java中的String类是重写了equals的,即对于传入对象,通过看源码可以发现,首先程序会对比两个对象地址是否相等,如果相等直接返回true,如果不相等会判断另一个对比对象是否是String类,如果是的话就会对比两个String对象的值。

在这种情况下,两个String对象即使地址不一样,因为值相同,equals也会返回true。

这时如果不重写hashCode,就会直接调用顶级父类Object的hashCode方法,即对该对象的地址求哈希值。那么会导致两个String对象equals为true,但hashCode却不相等。这样就违背了java中的规定:equals方法的结果必须与hashcode的结果保持一致,即equals为true时,hashcode必须相等。

否则(没有重写hashcode方法时)在java的一些类中,如hashMap,hashTable中,由于将键对值插入时会首先判断两个key对象的哈希值是否相等,以此判断这两个key对象是否相等,这时就会导致会同时插入
hashMap.put(“k”,“v1”)
hashMap.put(“k”:“v2”)
这样通过key来查找就会混乱。
这时即使我们重写了key对象的equals方法,也会导致两个key相等的对象作为多个key插入。
这就是为什么java中重点申明需要保证两个对象如果equals为true,那么两个对象的哈希值也必须一样。
当然,另外,即使两个对象哈希值相等,由于哈希碰撞也可能存在两个对象不相等,所以会继续判定两个对象是否地址相等或者是否equals为true。


由此,总的来说,如果在对象中重写了equals方法,那么必须要重写hashCode方法使得两个equals判定为true的对象,hashCode也必须相等,否则可能会在后续难以预料地出现诸多问题。如hashMap,hashTable,hashSet等等。
一个对象的hashCode是对于该对象的重要标识。hashCode的对比结果必须与equals方法的结果保持一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值