java 中为什么重写 equals 后需要重写 hashCode

1. 与方法的关系

这两个方法都是方法,也就是说如果一个对象没有重写这两个方法,默认会由类中的方法实现。他们的关系是:

如果通过 () 方法比较两个对象是否相等,则这两个对象必须相同。

如果两个对象相同,则不能证明这两个对象是同一个对象(不一定相等),只能证明这两个对象在哈希结构中存放在同一个地址(不同对象相同的情况是称为哈希冲突)。

2.为什么重写后还需要重写

Java 3rd 描述了为什么方法在被覆盖后必须被覆盖:

每个覆盖了equals方法的类中,必须覆盖hashCode。如果不这么做,就违背了hashCode的通用约定,也就是上面注释中所说的。
进而导致该类无法结合所以与散列的集合一起正常运作,这里指的是HashMap、HashSet、HashTable、ConcurrentHashMap。

上面的注解是类中的方法注解:

      If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.

结论:如果 不重写,它就不能很好地与散列收集一起工作。

3.举个例子进行论证分析

查看put方法

 public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);

    }

查看 hash 方法的实现:

  static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

    }

查看 get 方法的实现:

   public V get(Object key) {
        Node e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;

    }

java中的数据结构是数组+链表+红黑树;在这个数据结构中,每个键值对都会存储在对应的地址中。从代码中可以看出,当前key是由key的容量和自身对于value的存储索引()决定的,确定的位置后,进入进行判断和两种方法同时。也就是说,如果不同,那么就会创建一个新的Node键值对象。

放置键值对时,会先根据key和判断key是否已经存在于容器中。如果存在,它将被覆盖,反之亦然。所以如果我们在重写方法的时候不重写方法,该方法仍然会使用默认提供的原始方法,并且提供的方法的返回值不会重复(即每个对象返回的值不同) . 所以这将导致每个对象成为 .

反向参数:如果一个类重写了一个方法,但没有重写该方法;而类的两个对象属性不同但相等,当对象作为key进行存储时,会出现hash冲突,但是发现类重写了方法,经过类比较相等,只会保存一个对象,使用get方法获取时会获取其他对象,导致获取对象混淆。

所以,重写方法一定要重写方法,通过()方法保证两个对象比较相等,那么这两个对象的原理一定是一样的;

© 版权声明
THE END
喜欢就支持一下吧
点赞11赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容