1.首先,equals()和hashcode()方法都是從object類繼承的。?
equals()方法在object類中的定義如下:?
public boolean equals(Object obj){?
return(this = = obj);?
}?
顯然是比較兩個對象的地址值(即引用是否相同)。但我們必須清楚,當String、Math和Integer、Double。。。。當這些封裝的類使用equals()方法時,它們已經覆蓋了object類的equals()方法。比如在弦樂類:?
public boolean equals(Object an Object){?
if(this = = a object){?
返回true?
}?
if(字符串的壹個對象實例){?
String another String =(String)an object;?
int n = count?
if (n == anotherString.count) {?
char v 1[]= value;?
char v2[]= another string . value;?
int i = offset?
int j = anotherString.offset?
而(n -!= 0) {?
if (v1[i]!= v2[j])?
返回false?
}?
返回true?
}?
}?
返回false?
}?
很明顯,這是內容比較,不是地址比較。等等Double,Integer,Math。。。。以此類推,這些類都重寫了equals()方法,以便比較內容。當然基本類型是比較價值觀,這個沒什麽好說的。?
我們還要註意,Java語言對equals()有以下要求,必須遵循:?
對稱:如果x.equals(y)返回“真”,那麽y.equals(x)也應該返回“真”。?
Reflectivity: x.equals(x)必須返回“true”。?
類比:如果x.equals(y)返回true,y.equals(z)返回true,那麽z.equals(x)也應該返回true。?
有壹致性:如果x.equals(y)返回“真”,只要X和Y的內容不變,不管妳重復多少次x.equals(y),返回的都是“真”。?
在任何情況下,x.equals(null)總是返回“false”;X.equals(與X不同類型的對象)總是返回“false”。?
以上五點是重寫equals()方法時必須遵循的準則。如果違反了,就會出現意想不到的結果。請務必遵守。
2.其次,hashcode()方法在object類中定義如下:?
public native int hashCode();?
描述是壹個本地方法,它的實現與本地機器相關。當然,我們可以在自己的類中重寫hashcode()方法,比如String、Integer和Double。。。。等等,這些類都覆蓋了hashcode()方法。比如String類中定義的hashcode()方法如下:?
public int hashCode() {?
int h = hash?
if (h == 0) {?
int off = offset?
char val[]= value;?
int len = count?
for(int I = 0;我& ltlen我){?
h = 31*h?val[off];?
}?
hash = h;?
}?
返回h;?
}?
解釋壹下這個程序(用String的API寫的):?
s[0]*31^(n-1)?s[1]*31^(n-2)?...?s[n-1]?
使用int算法,其中s[i]是字符串的第I個字符,n是字符串的長度,0表示取冪。(空字符串的哈希碼為0。)?
這裏首先要明白壹個問題:?
對於equals()相等的兩個對象,Hashcode()必須相等;?
equals()不相等的兩個對象不能證明它們的hashcode()不相等。換句話說,兩個equals()方法不相等的對象,hashcode()可能相等。我的理解是哈希碼生成時的沖突造成的。?
反之:hashcode()不等於,equals()不等於;Hashcode()相等,equals()可以相等也可以不相等。解釋第3點的使用範圍。我的理解是可以用在object,String等類中。在object類中,hashcode()方法是壹個局部方法,返回對象的地址值,而object類中的equals()方法比較兩個對象的地址值。如果equals()相等,說明兩個對象的地址值相等,當然hashcode()也相等。在String類中,equals()返回兩個對象內容的比較。當兩個物體的內容相等時。
Hashcode()方法也可以根據String類重寫的代碼的分析知道Hashcode()返回的結果會相等(這壹點在第2點已經分析過了)。以此類推,我們可以知道,Integer、Double等封裝類中重寫的equals()和hashcode()方法也適合這個原理。當然,在繼承了object類的equals()和hashcode()方法後,任何重寫的類都不會遵循這個原則。?
4.說到hashcode()和equals(),就不能不談到在hashset、hashmap和hashtable中的使用。具體是什麽情況?請看以下分析:?
HashSet繼承了Set接口,Set接口實現了Collection接口,這是壹個層次關系。那麽hashset使用什麽原理來訪問對象呢??
hashset中不允許有重復的對象,元素的位置也是不確定的。如何判斷hashset中的元素是否重復?這就是問題的癥結所在。經過壹下午的詢問和求證,我終於有了壹些啟示。跟大家分享壹下吧。在java的集合中,判斷兩個對象是否相等的規則是:?
1),來判斷兩個對象的hashCode是否相等?
如果不相等,兩個對象不相等,over?
如果相等,請執行2)?
(這只是為了提高存儲效率。其實理論上沒有它也可以,但如果沒有,實際使用中效率會大打折扣,所以我們在這裏把它當做必需品。我們將在後面重點討論這個問題。)?
2)、用equals運算判斷兩個對象是否相等?
如果不相等,妳認為兩個物體不相等嗎?
如果相等,則認為兩個對象相等(equals()是判斷兩個對象是否相等的關鍵)?
為什麽有兩個標準?不能用第壹個嗎?不能,因為我之前說過,當hashcode()相等時,equals()方法可能不相等,所以必須用第二個準則來限制它,保證添加的元素不重復。?
例如,下面的代碼:
public static void main(String args[]){?
String s 1 =新字符串("趙旭東");?
字符串s2 =新字符串(“趙旭東”);?
system . out . println(s 1 = = S2);//假?
system . out . println(s 1 . equals(S2));//真?
system . out . println(s 1 . hashcode());//s1.hashcode()等於s2.hashcode()?
system . out . println(S2 . hashcode());?
set HashSet = new HashSet();?
hashset . add(s 1);?
hashset . add(S2);?
/*本質上,在將s1和s2相加時,利用上面提到的兩個準則,我們可以知道hashset認為s1和s2相等,並且是在添加重復元素,所以S2覆蓋了s 1;*/?
叠代器it=hashset。