##为什么要重写hashCode和equals方法?
1. 为什么要重写HashCode
和equals
方法?
当使用使用HashMap
存入数据的键:key
为自定义类时,需要重写;若不重写自定义类的HashCode
和equals
方法,所得结果与预期会不同。
2. 不重写HashCode
会有什么后果?
首先需要强调一点,Object
类的固有方法是根据两个对象的内存地址来判断,我对Object
不甚了解,这里暂时先记着。
不重写HashCode
,则存入自定义类时计算其hash
值用的是默认的Object
类的HashCode
方法,该方法返回的hash
值是传入自定义类对象的地址
。
若以自定义类的对象作Key
的话,以值(id=1
)为1
的对象k1
作键先存入一条数据value="001"
,再以值为id=1
的对象k2
来取出数据,得到的是null
,因为HashMap
中存的是<k1的地址,"001">
,而传入的却是k2
的地址,k1
和k2
的地址明显是不同的,所以会返回null
。
3. 重写了HashCode
不重写equals
方法会有什么后果?
这里再次注明一点,由于hash
存在冲突,所以HashMap
采用链地址法来处理冲突,对应同一hash
值的键将组成一个链表。
即不同的值可能对应同一hash
值。
而equals
方法就是用来判断传入数据是否真的是要找的数据的。
所以如果重写了HashCode
却没有重写equals
方法,会出现即使根据hash
查找这一步没出错,但在执行equals
方法时却会因为k2
和k1
的地址不同而返回null
。
4. HashCode
和equals
方法都重写了,那这时的HashMap
get流程是怎样的?
创建自定义类的对象k1
、k2
,id
属性都设为1
。创建一个HashMap
实例hm
。执行:
hm.put(k1, "Key with id is 1");
然后执行:
System.out.println(hm.get(k2));
get
的流程为:
1.因为重写了HashCode
方法,所以现在是根据k2
的id=1
来计算hash
;
2.因为k1
的id=1
跟k2
的id=1
相等,所以根据HashCode
方法计算出来的hash
会找到k1
,此时还不能判断相等;
3.调用equals
方法来判断,这里只要是两个对象(k1
、k2
)的类型都为Key
且id
相等,就判断相等,这里k1
、k2
都相等,且id
都为1,故判断get
成功,返回结果。
Key的定义
class Key {
private Integer id;
public Integer getId() {
return id;
}
public Key (Integer id) {
this.id = id;
}
public boolean equals(Object o) {
if (o == null || !(o instanceof Key)) {
return false;
}else {
return this.getId().equals(((Key) o).getId());
}
}
public int hashCode() {
return id.hashCode();
}
}
个人理解,难免有不当之处,还望指正