主要原因是默認從Object繼承來的hashCode是基於對象的ID實現的。
如果你重寫了equals,比如說是基於對象的內容實現的,而保留hashCode的實現不變,那么很可能某兩個對象明明是“相等”,而hashCode卻不一樣。
這樣,當你用其中的一個作為鍵保存到hashMap、hasoTable或hashSet中,再以“相等的”找另一個作為鍵值去查找他們的時候,則根本找不到。
資源:http://lelglin.iteye.com/blog/1826152
我們都知道Java語言是完全面向對象的,在java中,所有的對象都是繼承於Object類。Ojbect類中有兩個方法equals、hashCode,這兩個方法都是用來比較兩個對象是否相等的。
在未重寫equals方法我們是繼承了object的equals方法,那里的 equals是比較兩個對象的內存地址,顯然我們new了2個對象內存地址肯定不一樣
- 對於值對象,==比較的是兩個對象的值
- 對於引用對象,比較的是兩個對象的地址
默認的equals方法同==,一般來說我們的對象都是引用對象,要重寫equals方法。
現在有一個學生對象,有屬性學號跟姓名,現在我新建了一個學生對象,又從數據里查出一個學生對象,這兩個對象的學號跟姓名都一樣,那這兩個對象是不是相等呢?一般情況下,除非你有特殊需求要處理,這兩個對象是相等的,可如果用==去比較,返回的結果是錯誤的。
這時候我們就必須重寫equlas方法了。如果學號是主鍵,在equals方法里,我們認為只要學號相同,就可以返回true。
hashCode方法也是可以用來比較兩個對象是否相等的。但是我們很少使用,應該說是很少直接使用。hashCode方法返回的是一個int值,可以看做是一個對象的唯一編碼,如果兩個對象的hashCode值相同,我們應該認為這兩個對象是同一個對象。
一般如果使用java中的Map對象進行存儲時,他會自動調用hashCode方法來比較兩個對象是否相等。
所以如果我們對equals方法進行了重寫,建議一定要對hashCode方法重寫,以保證相同的對象返回相同的hash值,不同的對象返回不同的hash值。
如上面的學生例子,如果學號相同,不管姓名相不相同,返回的hash值一定要是一樣的,這時我們的hash值只與學號有關。
- public class Test
- {
- public static void main(String[] args)
- {
- HashMap hm = new HashMap();
- hm.put(new key(1),new value(2));
- if(hm.containsKey(new key(1)))
- System.out.println(hm.get(new key(1)));
- else
- System.out.println("dont have such a key");
- }
- }
你每次new 一個新對象出來hashcode肯定不一樣,所以你拿不到你要的key。
- class key
- {
- int i ;
- public key(int i)
- {
- this.i = i;
- }
- @Override
- public boolean equals(Object obj)
- {
- if(obj instanceof key)
- {
- if(((key)obj).i == i)
- return true;
- }
- return false;
- }
- @Override
- public int hashCode()
- {
- return i;
- }
- }
1、重寫equals方法時需要重寫hashCode方法,主要是針對Map、Set等集合類型的使用;
a: Map、Set等集合類型存放的對象必須是唯一的;
b: 集合類判斷兩個對象是否相等,是先判斷equals是否相等,如果equals返回TRUE,還要再判斷HashCode返回值是否ture,只有兩者都返回ture,才認為該兩個對象是相等的。
2、由於Object的hashCode返回的是對象的hash值,所以即使equals返回TRUE,集合也可能判定兩個對象不等,所以必須重寫hashCode方法,以保證當equals返回TRUE時,hashCode也返回Ture,這樣才能使得集合中存放的對象唯一。