为什么要重写hashCode()、equals()。

借鉴一下大佬的文章:https://zhuanlan.zhihu.com/p/78249480

场景

当对HashMap进行操作的时候 我们想完成这样的目的:在HashMap的“键”部分存放自定义的对象。

  • 原始get首先经过Hashcode值判断、在经过equals()判断才能取到值。(不对的地方请指正)
import java.util.HashMap;
2   class Key {
    
    
3       private Integer id;
4       public Integer getId()
5   {
    
    return id; }
6       public Key(Integer id)
7   {
    
    this.id = id;  }
8   //故意先注释掉equals和hashCode方法
9   //  public boolean equals(Object o) {
    
    
10  //      if (o == null || !(o instanceof Key))
11  //      { return false; }
12  //      else
13  //      { return this.getId().equals(((Key) o).getId());}
14  //  }
15     
16  //  public int hashCode()
17  //  { return id.hashCode(); }
18  }
19 
20  public class WithoutHashCode {
    
    
21      public static void main(String[] args) {
    
    
22          Key k1 = new Key(1);
23          Key k2 = new Key(1);
24          HashMap<Key,String> hm = new HashMap<Key,String>();
25          hm.put(k1, "Key with id is 1");    
26          System.out.println(hm.get(k2));    
27      }
28  }

k1,k2对象的id值相同,我们向根据根据k2的id值去map去k1的value。

重写前和重写后的情况对比

  • 没有重写 Hashcode情况;
  • 有在Key里定义hashCode方法。这里调用的仍是Object类的hashCode方法(所有的类都是Object的子类),而Object类的hashCode方法返回的hash值其实是k1对象的内存地址。 但是k1、k2只是值相同,地址不同。
  • 重写Hashcode、未重写equals情况:
  • 经过Hashcode后,k1、k2对象确实会指向同一个hashcode值下、以链表形式出现:
    在这里插入图片描述

原始Object的equals方法对比的是对象1 和 对象2 的内存地址、对象1 和 对象2地址是不一样的 、 如果没重写肯定equals返回false、重写后才能根据id值找到同一个 Map的value。

总结

重申一下,如果大家要在HashMap的“键”部分存放自定义的对象,一定要在这个对象里用自己的equals和hashCode方法来覆盖Object里的同名方法。

Guess you like

Origin blog.csdn.net/qq_36737214/article/details/119342590