1. 程式人生 > >Java用自定義的類型作為HashMap的key

Java用自定義的類型作為HashMap的key

str boolean 順序 string 函數 出現 print 重新 對象

??需要重寫hashCode()和equals()方法才可以實現自定義鍵在HashMap中的查找。

public class PhoneNumber
{
    private int prefix; //區號
    private int phoneNumber; //電話號

    public PhoneNumber(int prefix, int phoneNumber)
    {
        this.prefix = prefix;
        this.phoneNumber = phoneNumber;
    }
}
import java.util.HashMap;

public class Test1
{
    public static void main(String[] args)
    {
        HashMap<PhoneNumber, String> map = new HashMap<>();

        map.put(new PhoneNumber(027, 12345678), "zhangsan");
        map.put(new PhoneNumber(027, 22222222), "lisi");
        map.put(new PhoneNumber(027, 33333333), "wangwu");
        map.put(new PhoneNumber(027, 33333333), "abc");

        System.out.println(map.toString());

        System.out.println(map.get(new PhoneNumber(027, 12345678)));
        System.out.println(map.get(new PhoneNumber(027, 22222222)));
        System.out.println(map.get(new PhoneNumber(027, 33333333)));
    }
}

運行結果為:

[email protected]=zhangsan, [email protected]=wangwu, [email protected]=lisi, [email protected]=abc}
null
null
null

從中我們可以看到出現了兩個問題:

  • new PhoneNumber(027, 33333333)這個鍵被添加了兩次,但是在HashMap中wangwu和abc同時存在了
  • 使用get方法取得的值均為null

正確的方法就是直接對PhoneNumber類進行修改,覆蓋equals和hashCode方法,修改後的PhoneNumber類如下:

public class PhoneNumber
{
    private int prefix; //區號
    private int phoneNumber; //電話號

    public PhoneNumber(int prefix, int phoneNumber)
    {
        this.prefix = prefix;
        this.phoneNumber = phoneNumber;
    }

    @Override
    public boolean equals(Object o)
    {
        if(this == o)
        {
            return true;
        }
        if(!(o instanceof PhoneNumber))
        {
            return false;
        }
        PhoneNumber pn = (PhoneNumber)o;
        return pn.prefix == prefix && pn.phoneNumber == phoneNumber;
    }

    @Override
    public int hashCode()
    {
        int result = 17;
        result = 31 * result + prefix;
        result = 31 * result + phoneNumber;
        return result;
    }
}

重新執行上述函數,結果為:

[email protected]=abc, [email protected]=zhangsan, [email protected]=lisi}
zhangsan
lisi
abc

可以看到,之前出的錯誤都被改正了

在HashMap中,查找key的比較順序為:

  1. 計算對象的HashCode,看在表中是否存在
  2. 檢查HashCode位置中的對象是否與當前對象相等

以上使用計算HashCode的方法在effective java第九點中提到:

    • 對於對象中每個關鍵域f,為該域計算int類型的散列碼c,result = 31 * result + c

Java用自定義的類型作為HashMap的key