出自:http://blog.csdn.net/renfufei/article/details/16339351
Java語言是完全面向對象的,在java中,所有的對象都是繼承於Object類。Ojbect類中有兩個方法equals、hashCode,這兩個方法都是用來比較兩個對象是否相等的。在沒有重寫equals方法我們是繼承了object的equals方法,那里的 equals是比較兩個對象的內存地址,顯然我們new了2個對象內存地址肯定不一樣。
對equals方法進行了重寫,建議一定要對hashCode方法重寫,以保證相同的對象返回相同的hash值,不同的對象返回不同的hash值。
1. 錯誤使用方式
下面是一個常見的錯誤用法:
import java.util.HashMap; public class Apple { private String color; public Apple(String color) { this.color = color; } public boolean equals(Object obj) { if (!(obj instanceof Apple)) { return false; } if (obj == this) { return true; } return this.color == ((Apple) obj).color; } public static void main(String[] args) { Apple a1 = new Apple("green"); Apple a2 = new Apple("red"); //hashMap stores apple type and its quantity HashMap<Apple, Integer> m = new HashMap<Apple, Integer>(); m.put(a1, 10); m.put(a2, 20); System.out.println(m.get(new Apple("green"))); } }
在此示例中,hashMap 已經保存了一個綠色的Apple對象,但想(通過程序中的方式)從map獲取此對象時,apple 對象並未被找到.
上述代碼的輸出結果是: null. 但通過斷點調試,可以確定此對象已經存在於hashMap中,截圖如下:
2. 此問題由hashCode()引起
問題的原因是沒有重寫"hashCode()"方法.
equals()方法與hashCode()的通用協定是:
2.1 如果兩個對象相等(equal),那么必須擁有相同的哈希碼(hash code)
2.2 即使兩個對象有相同的哈希值(hash code),他們不一定相等.
Map的核心思想就是可以比線性查找更快. 通過散列值(hash)作為鍵(key)來定位對象的過程分為兩步:
在Map內部,存儲着一個頂層數組,頂層數組的每個元素指向其他的數組,查找或存儲的時候,先根據key對象的hashCode()值計算出數組的索引,然后到這個索引找到所指向的第二層線性數組,使用equals方法來比較是否有相應的值(以返回或者存儲).
Object類中的hashCode()默認為每個對象返回不同的int值,因此在上面的例子中,兩個相等(equal)的對象,返回了不同的hashCode值.
解決方法是為此類添加hashCode方法,比如,使用color字符串的長度作為示范:
public int hashCode(){ //此種實現,要求 color值定以后就不得修改 //否則同一個物理對象,前后有兩個不同的hashCode,邏輯上就是錯的 return this.color.length(); }