在每乙個覆蓋equals方法的類中,都必須覆蓋hashcode方法,如果不這麼做,會導致這個類無法結合所有基於雜湊的集合的正常使用,如hashmap,hashset,hashtable。
object規範中有這麼一條:
如果兩個物件根據equals(object)方法比較是相等的,那麼呼叫這物件中任意乙個物件的hashcode方法都必須產生同樣的整數結果。因為對於兩個物件a和b,如果a.equals(b)為true,則代表a與b在邏輯上是相等的,但是object中的hashcode方法,則是根據物件的記憶體位址來生成hashcode,這也就會導致兩個邏輯上相等的物件的hashcode卻是不同的。這在使用基於hashcode的雜湊表(如hashmap)時會出現問題:
public
class
phonenumber
@override
public
boolean
equals(object o)
if(!(o instanceof phonenumber))
phonenumber pn = (phonenumber)o;
return pn.linenumber == linenumber
&& pn.prefix == prefix
&& pn.areacode == areacode;
}}
map
string> m = new hashmapstring>();
m.put(new phonenumber(707, 867, 5309), "jenny");
m.get(new phonenumber(707, 867, 5309)); //return
null
因為在hashmap中,會先根據傳入物件的hashcode找到相應的桶,然後再在桶中尋找相等的物件,換言之如果連兩個物件的hashcode都不同,那麼也不會去比較這兩個物件是否相等。
乙個好的hashcode方法將會為不同的物件產生不同的hashcode,在最理想的情況下,應該把集合中所有不相等的物件均勻分布到所有可能的值上。
在hashcode的計算過程中,可以將冗餘域(即可以通過參與計算的其它值計算出來的值)排除在外,還有必須排除equals方法中沒有的所有值,否則有可能出現兩個物件邏輯相等但是生成的不同的狀況。
如果乙個類中參與hashcode計算的變數都是不可變(final)的,而且hashcode計算的開銷又非常大,那麼可以在建立這個物件,或第一次使用hashcode時計算這個值,然後將hashcode儲存在這個物件內部。
覆蓋equals總要覆蓋hashCode
1 通過物件位址,判斷兩個物件是否相等 public native int hashcode 2 equals 在沒有覆蓋object的equals之前,相當於 public boolean equals object obj 為什麼覆蓋equals總要覆蓋hashcode 1 equals應該提供...
覆蓋equals時遵守通用約定
類的每個例項都只與它自身相等。1,類的每個例項本質都是唯一的。2,不關心類是否提供了 邏輯相等 的測試功能。3,超類以及覆蓋了equals,從超類繼承過來的行為對於子類也是合適的。4,類是私有的或是包級私有的,可以確定它的equals方法永遠不會被呼叫。equals方法實現了等價關係 1,自反性。x...
覆蓋equals時遵守通用約定
不覆蓋equals時,類的每個例項都只與它自己相等。如果類有自己的邏輯相等概念,且超類未覆蓋equals以實現期望的行為,這時需覆蓋equals。約定內容 1.自反性 對於任何非null的引用值x,x.equals x 必須返回true 2.對稱性 對於任何非null的引用值x和y,當且僅當y.eq...