专业的JAVA编程教程与资源

网站首页 > java教程 正文

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

temp10 2025-01-02 19:14:34 java教程 9 ℃ 0 评论


公众号 《java编程手记》记录JAVA学习日常,分享学习路上点点滴滴,从入门到放弃,欢迎关注

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

前言

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


hashCode

 public native int hashCode();

hashCode方法用来获取当前对象的哈希码,也称为散列码,本质上是一个int类型的整数。哈希码的作用是确定该对象在我们常见的Java集合中如HashMapHashtableHashSet中的位置,每个对象对应的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



Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表