美文网首页
java 中为什么重写 equals 后需要重写 hashCod

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

作者: Java编程日记 | 来源:发表于2022-04-23 20:10 被阅读0次
    1. equals 和 hashCode 方法之间的关系
      这两个方法都是 Object 的方法,意味着 若一个对象在没有重写 这两个方法时,都会默认采用 Object 类中的方法实现,它们的关系为:

    如果两个对象通过equals()方法比较相等,那么这两个对象的hashCode一定相同。

    如果两个对象hashCode相同,不能证明两个对象是同一个对象(不一定相等),只能证明两个对象在散列结构中存储在同一个地址(不同对象hashCode相同的情况称为hash冲突)。

    2.为什么重写equals 后需要重写 hashCode
    Effective Java 第三版 中 描述为什么重写equals 方法后必须重写hashCode 方法:
    每个覆盖了equals方法的类中,必须覆盖hashCode。如果不这么做,就违背了hashCode的通用约定,也就是上面注释中所说的。
    进而导致该类无法结合所以与散列的集合一起正常运作,这里指的是HashMap、HashSet、HashTable、ConcurrentHashMap。
    上面注释 为 Object 类中 hashCode 方法注释:

    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.
    结论: 如果重写equals不重写hashCode它与散列集合无法正常工作。

    1. 以 HashMap 为例进行论证分析
      查看 hashMap 的 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<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
    }
    java中HashMap的数据结构是数组+链表+红黑树;这种数据结构,每个键值对都会被存在相应的地址中,从代码中可以看出HashMap是通过key的hashCode以及自身的容量来决定当前键值的存储索引(桶)的,确定桶的位置后,再进入桶中同时判断hashCode和equals两个方法。那也就是说,如果hashCode不同,那么HashMap就一定会创建一个新的Node键值对象。

    HashMap在put一个键值对时,会先根据键的hashCode和equals方法来同时判断该键在容器中是否已经存在,如果存在则覆盖,反之新建。所以如果我们在重写equals方法时,没有重写hashCode方法,那么hashCode方法还是会默认使用Object提供的原始方法,而Object提供的hashCode方法返回值是不会重复的(也就是说每个对象返回的值都不一样)。所以就会导致每个对象在HashMap中都会是一个新的键。

    反向论证:若一个类中重写了 equals 方法,没有重写hashCode方法;且该类的两个对象具有不同属性但 hashCode 相等,在hashMap 以该对象为键进行存储时,会出现hash冲突现象,但发现该类重写了equals 方法,且通过该类的equals 比较之后也是相等,就会出现 hashMap 中只保存了一个对象,采用get 方法获取时,就会获取到别的对象,从而导致获取对象错乱。

    因此 重写equals 方法必须重写 hashCode 方法,用来保证两个对象通过equals()方法比较相等,那么这两个对象的hashCode一定相同 这一原则;

    相关文章

      网友评论

          本文标题:java 中为什么重写 equals 后需要重写 hashCod

          本文链接:https://www.haomeiwen.com/subject/jhcoertx.html