Java中为什么要同时重写equals()和hashcode()方法

1. 背景

        String a=new String("123");
        String b=new String("123");

我们知道,在java中 a == b 比较的是对象的在内存中的物理地址,equals()方法的作用本来和==相同,也是比较两者的物理地址,但String类重写了equals()方法,于是String类的equals方法变成了比较两个字符串对象的字符串内容是否相等。

2. equals()hashcode()方法需要同时重写的原因

首先,我们要明白hashCode()方法的作用是确定对象在散列存储结构例如HashMapHashSet中的存储地址。

注:这个地址不是对象在内存中的真实存储地址,只是在数据结构中的逻辑地址

那么,我们就能知道为什么重写equals()方法同时要重写hashcode()方法了:
因为,如果重写了equals()方法,没有重写hashCode()方法的话,如果a.equals(b),但a的hashCode与b的hashCode不相等,则当我们将a、b同时加入散列存储结构map、set时,就可能出现数据结构中存在两个值相等的对象的情况,从而导致混淆。

示例:

        String a=new String("123");
        String b=new String("123");
        System.out.println(a==b);   //false
        System.out.println(a.equals(b));    //true
        System.out.println(a.hashCode()==b.hashCode());    //true

        Set<String>set=new HashSet<>();
        set.add(a);
        System.out.println(set.contains(b));   //true

以上例子可以看出,虽然ab不是同一个对象,但是由于表达式a.equals(b)结果是true,所以a的hashCode与b的hashCode相等,两者在set中存储地址相同,在set中加入a后,在set中查询b,返回结果是true。如果仅重写了equals方法,而没有重写hashcode方法,那就有可能出现a.equals(b)==ture,但是set.contais(b)返回的却是false;

综上,重写equals()方法同时尽量也要重写hashcode()方法。

3. 重写equals方法遵循的原则

hashCode并不需要唯一性,但equals必须严格地判断两个对象是否相同。

正确的equals方法有如下特性:

  • 自反性x.equals(x)一定返回true
  • 对称性:如果x.equals(y)true,那么y.equals(x)也为true
  • 传递性:如果x.equals(y)truey.equals(z)true,那么x.equals(z)也为true
  • 一致性:如果xy中用于等价比较的信息没有改变,那么x.equals(y)无论调用多少次,结果都一致
  • 任何不是nullxx.equals(null)一定返回false

4. equals与hashCode的相关规定

之所以有规定,是为了使诸如HashMap这样的哈希表正常使用。具体规定如下:

  • equals相等,hashcode一定相等。
  • equals不等,hashcode不一定不等。
  • hashcode不等,equals一定不等。
  • hashcode相等,equals不一定相等。

5. 参考:

  1. https://blog.csdn.net/CY2333333/article/details/119010159
  2. https://blog.csdn.net/xl_1803/article/details/111941059
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值