文章出處

在Java的基類java.lang.Object中有兩個非常重要的方法:

public boolean equals(Object obj)
public int hashCode()

對這兩個方法的理解非常重要,特別是當用戶自己定義對象,并將其存入到Map中的時候;

然而,即便是高級開發人員,有時候也搞不清楚如何正確的使用它們;

在這篇文章,我首先會展示一種常見的錯誤示例,然后解釋如何正確的使用這兩個方法;

常犯的錯誤

如下代碼是常見的錯誤使用示例:

package simplejava;

import java.util.HashMap;

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.equals(((Apple) obj).color);
    }

}

public class Q9 {
    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中,但是當我們要取出來的時候,得到的卻是null;然而通過調試程序,我們確實看到了hashmap中的綠蘋果對象;

錯誤原因-hashcode()方法導致

之所以出現這個錯誤是因為沒有重寫hashCode()方法導致的。

hashCode()和equals()的關系是這樣的:

如果兩個對象相等(equal),它們的hashcode一定相同;

如果兩個對象有相同的hashcode,它們不一定相等(equal);

之所以這樣設計是為了在Map中更快的查找到對象(相對于線性搜索);

一般Map都設計成數組+鏈表的結構,使用hashcode去查找對象需要兩個步驟,首先使用hashcode定位數組下標索引,然后遍歷該數組元素對應的鏈表,找到equals的元素;

Object默認的hashcode實現對于不同的對象會返回不同的值,因此,在上面那個例子中,不同的對象(即使同一個類型)有著不同的hashcode;

值的散列就像在車庫儲存貨物,不同的貨物能被存放到不同的車庫。比較有效查找貨物辦法是將不同的貨物存到不同的車庫中,而不是同一個車庫;

所以將hash值盡可能的分散是一個比較好的策略;

關于這個例子,解決辦法是添加hashcode方法,這里我將使用顏色的長度作為示范,如下代碼:

public int hashCode(){
    return this.color.length();
}

 

譯文鏈接:http://www.programcreek.com/2011/07/java-equals-and-hashcode-contract/


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()