您的位置 首页 java

为什么重写 equals时必须重写 hashCode 方法?

前言

直接进入正题, hashCode 方法和 equals 方法

hashCode

  public native int hashCode();  

hashCode 方法用来获取当前对象的 哈希码 ,也称为 散列码 ,本质上是一个int类型的整数。哈希码的作用是确定该对象在我们常见的Java集合中如 HashMap Hashtable HashSet 中的位置,每个对象对应的 hashCode 不一样,避免在集合类中进行存放时出现 hash 碰撞

equals

   public boolean equals(Object obj) {
         return (this == obj);
     }  

默认 equals 方法的实现为直接对象两个对象的是否在内存中为同一个对象,在我们日常开发中,使用equals方法更多的是判断两个对象是否 相等 ,而非是同一个对象,所以会重写 equals 方法,如 Integer 中, equals 方法对比的是对应包装的基本类型 int 的值,同样 Integer 中也重写了 hashCode 方法,保证 相同 对象返回的 hashCode 也保持一致

  public boolean equals(Object obj) {
         if (obj instanceof Integer) {
             return value == ((Integer)obj).intValue();
         }
         return false;
 }
 
 @Override
 public int hashCode() {
   return Integer.hashCode(value);
 }
 
 public static int hashCode(int value) {
         return value;
 }  

那为什么要在重写 equals 的同时,重写 hashCode 方法呢,或者更加准确地说,为什么在重写 equals 方法的同时,重写 hashCode 方法来保证 equals 方法结果为 true 时, hashCode 也相等呢

本质上,当两个对象相等时,在 散列表 中的位置应当是一致的,而在散列表中,计算对象存放位置的方式就是通过 hash 算法计算对象的 hashCode 得到 hash 值,如 HashMap 中,设置 kv 时,需要先计算 hash 值来确认槽位, hash 值则通过 hashCode 运算得到

  public V put(K key, V value) {
     return putVal(hash(key), key, value, false, true);
 }
 
 static final int hash(Object key) {
         int h;
         return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
 }  

同样在获取对应值时,则先通过 hash 值进行槽定位获取,当计算的 hash 值不相同时,就可能出现 put 进去数据但获取不到的尴尬结果

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

同时,计算hashCode要避免变量性强的字段,当hashCode的计算涉及到某些变量时,改变变量的值后,可能就取不出来了

  @Data
 public class Data implements Serializable {
   
   private Integer id;
   
    public boolean equals(Object obj) {
         if(obj instanceof Data){
             Data obj1 = (Data) obj;
             return obj1.id == this.id;
         }
         return false;
     }
 
     @Override
     public int hashCode() {
         return id+1;
     }
 }
 
 
 public static void main(String[] args) {
         Data data = new Data();
         data.setId(1);
         Map<Data, Integer> map = new HashMap<>();
         map.put(data,1);
         System.out.println(map.get(data));
         data.setId(2);
         System.out.println(map.get(data));
 }  

输出结果为

  1
 null  

文章来源:智云一二三科技

文章标题:为什么重写 equals时必须重写 hashCode 方法?

文章地址:https://www.zhihuclub.com/170175.shtml

关于作者: 智云科技

热门文章

网站地图