淺談hashcode()和equals()方法
Java Object 類中存在hashcode()方法以及equals方法
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
hashCode方法是一個本地方法用於獲取一個對像的hash值,equals方法用於比較兩個物件的地址是否相等。
我們判斷一個物件相等的條件是:
兩個物件的hash值相等且equals方法返回ture.
例如String類重寫了equals方法,用於比較內容。
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
從程式碼可以看出,如果物件地址相同直接返回true,否則比較內容,如果內容相同則返回true否則返回false.
在沒有重寫equals方法前加入有兩個物件 str1 str2 ,兩者的hash值大概率是不相等的,equals 也是不等的,重寫後equals相等,那麼hash值也應相等,所以要重新寫hashcode(),利用字串的每一位做hash那麼兩個內容相同的字串hash必定相同。
public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
在Java API文件中關於hashCode方法有以下幾點規定:
1 在java應用程式執行期間,如果在equals方法比較中所用的資訊沒有被修改,那麼在同一個物件上多次呼叫hashCode方法時必須一致地返回相同的整數。如果多次執行同一個應用時,不要求該整數必須相同。
2 如果兩個物件通過呼叫equals方法是相等的,那麼這兩個物件呼叫hashCode方法必須返回相同的整數。
3. 如果兩個物件通過呼叫equals方法是不相等的,不要求這兩個物件呼叫hashCode方法必須返回不同的整數。但是程式設計師應該意識到對不同的物件產生不同的hash值可以提供雜湊表的效能。
應用於map型別的資料結構時特別明顯:
Map中的key值是根據hashcode實現的,eg,set集合,如果重寫了equals方法,如String類,如果不重寫hashcode()則可能會存入兩個相同的字串,這和set的集合特性不一致。