借鉴一下大佬的文章: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里的同名方法。