今天在用阿里代碼檢查工具檢查項目的時候,發(fā)現(xiàn)了一個警告
Map/Set的key為自定義對象時沛申,必須重寫hashCode和equals
說明為:
1) 只要重寫equals铁材,就必須重寫hashCode奕锌。 ?
2) 因為Set存儲的是不重復(fù)的對象惊暴,依據(jù)hashCode和equals進行判斷,所以Set存儲的對象必須重寫這兩個方法肄鸽。 ?
3) 如果自定義對象做為Map的鍵油啤,那么必須重寫hashCode和equals益咬。
下面是代碼的寫法(偽代碼)
public void methodDemo(){
Set<ObjDemo> hashSet = new HashSet();
hashSet.add(new ObjDemo("1","對象1"));
hashSet.add(new ObjDemo("2","對象2"));
}
ObjDemo類很簡單
class ObjDemo{
private String id;
private String name;
public ObjDemo(String id,String name){
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
為什么會報這個警告幽告?
警告中也說明了,因為Set存儲的是不重復(fù)的對象齐唆,依據(jù)hashCode和equals進行判斷冻河,所以Set存儲的對象必須重寫這兩個方法芋绸。
了解hashSet存儲對象的方式,請參考:http://www.reibang.com/p/6cab0fae2403
equals和hashCode的關(guān)系(這個是規(guī)定):
1廷蓉、如果兩個對象相同(即用equals比較返回true)桃犬,那么它們的hashCode值一定要相同;
2土匀、如果兩個對象的hashCode相同形用,它們并不一定相同(即用equals比較返回false)
hashCode()方法是干什么的田度,這里提示了是重寫,那么原來其實是有一個hashCode的乎莉,在Object類中奸笤,這里的hashCode()存放的是對象的內(nèi)存地址
所以我們在存放對象進入hashSet的時候监右,如果不重寫equals()和hashCode(),像下面這段代碼
public void methodDemo(){
Set<ObjDemo> hashSet = new HashSet();
hashSet.add(new ObjDemo("1","對象1"));
hashSet.add(new ObjDemo("1","對象1"));
}
其實我們邏輯上放進去的是一個對象秸侣,因為id宠互、name都相等予跌,但是,如果打斷點或者寫個測試方法去輸出hashSet長度的時候,會發(fā)現(xiàn)在hashSet中卻有兩個對象频轿,因為這兩個對象的內(nèi)存地址是不同的烁焙。所以要重寫equals()和hashCode()方法骄蝇。例如根據(jù)id來比較兩個對象是否相等,以及根據(jù)id取hashCode赚窃,在ObjDemo中加入
@Override
public boolean equals(Object o) {
if (o instanceof ObjDemo){
ObjDemo obj = (ObjDemo)o;
return id.equals(obj.id);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
這樣往hashSet中放對象時就會根據(jù)id去判斷勒极,不會重復(fù)添加。
面試題:為什么重寫equals()方法要重寫hashCode()方法
從上面的規(guī)定可以知道键痛,如果只重寫了equals()方法不重寫hashCode()方法掀鹅,那么則違反了如果兩個對象相同(即用equals比較返回true)乐尊,那么它們的hashCode值一定要相同
也可以把上面的代碼中的hashCode()方法去掉,添加2個id為1的對象限府,set集合里的數(shù)據(jù)還是為2條胁勺。
所以得出結(jié)論:如果一個類重寫了equals方法但是沒有重寫hashCode方法独旷,那么該類無法結(jié)合所有基于散列的集合(HashMap嵌洼,HashSet)一起正常運作。