簡體   English   中英

對象作為沒有Hashcode和equals的Map鍵

[英]Objects as Map keys without Hashcode and equals

public class Contact
{
    int i;
    String name;
    public Contact(int iVal, String nameVal)
    {
        i = iVal;
        name = nameVal;
    }
}   

public class MultiMap
{
    public static void main (String args[])
    {
        java.util.HashMap m = new java.util.HashMap();
                Contact m1 = new Contact(1, "name");
        Contact m2 = new Contact(1, "name");
        m.put(m1, "first");
        m.put(m2, "second");
        System.out.println(m.get(m1));
        System.out.println(m.get(m2));
    }
}   

輸出是:

first 
second 

這種“獲取”方法如何表現? 由於m1和M2具有相同的值並且我沒有覆蓋hashcode(),所以會調用Object類的equals()方法嗎?

這個對嗎 ?

  1. 沒有哈希碼方法,因此JVM無法查看對象m1和m2是否包含不同的值
  2. 沒有重寫equals方法,因此調用了Object類的equals(),並且由於兩個對象都不同,上面的代碼工作正常,而m2不替換m1的值。

當您的類不覆蓋hashCode()equals(Object o)方法時,Java只使用對內存中對象的實際引用來計算值(即檢查它是否與該類的實例相同)。 這就是為什么你仍然得到兩個結果。

所有對象都有hashCode()和equals()。 如果未覆蓋它們,則使用默認實現。 默認行為是將所有對象視為不同,除非它們是同一個對象。

為了進行比較,即使您已覆蓋hashCode和equals,IdentityHashMap也會始終執行此操作。

它將使用對象類的equals和hashcode方法來查找值(因為Contact不會覆蓋equals和hashcode方法),所以是的。

  1. 是的,Java將始終看到兩個Contact對象是不同的,因為它將使用對象引用來比較它在對象中使用equals方法時
  2. 是的,因為兩個聯系對象必須引用。

默認情況下,Object類重寫hashCode和equals方法。 這就是您獲得所需輸出的原因。

如果不重寫equals和hashcode方法,JVM會在場景后面檢查它。 由於m1和m2都是不同的對象實例,因此equals方法始終返回false。 即:

1.等於:

m1.equals(m2)//返回false,因為兩者都是不同的實例。

2.對於hashCode: //查看HashMap.java中的源代碼

在放入hashMap之前,HashMap內部使用reshsh鍵。 見下文。

[![Source code of put method][1]][1]
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

對於rehash,hashMap有自己的靜態哈希方法:

[![Source code of hash method][1]][1] 
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

在內部,equals和hashCode方法都以這種方式工作,這就是為什么你得到存儲在HashMap中的兩個值的原因。

希望這可以幫助 :)

Contact類中,您沒有實現hashcode()equals()函數。

當HashMap調用這些方法時,它將在父類中搜索這些方法,在這種情況下是Object。

在這種情況下,將評估堆上的對象位置而不是值。

例如,對於兩個對象o1o2

o1.equals(o2) == true僅當o1 == o2時才為o1.equals(o2) == true

hashCode()是Object類的方法。 散列碼是JVM對象的整數表示。 散列碼是系統生成的,JVM將對象的地址作為基礎(種子)來生成散列碼。 生成的散列碼在不同的執行時間內不必相同。

是的,這是正確的。 任何沒有定義自己的equals和hashcode方法的java對象都會繼承java.lang.Object上的默認equals和hascode方法。 這些默認實現基於對象引用相等,而不是邏輯上相等。 由於您使用相同的對象引用調用了get,因此可以從地圖返回該對象。

這是一個進一步說明這一點的例子。

java.util.HashMap m = new java.util.HashMap();
Contact m1 = new Contact(1, "name");
Contact m2 = new Contact(1, "name");
m.put(m1, "first");
m.put(m2, "second");
System.out.println(m.get(m1));//first 
System.out.println(m.get(m2));//second
System.out.println(m.get(new Contact(1, "name"));//null - since the new object has a different object reference.

雖然m1和m2具有相同的值,但它們是不同的對象引用。

這是正確的:沒有hashcode方法,因此JVM無法查看對象m1和m2是否包含不同的值 - >因此它使用Object類的hasCode()方法來計算hashCode值以執行get() ,返回不同的哈希值(顯而易見)。

第二點也是正確的:因為你沒有實現自己的equals(),所以會考慮Object的equals(),它只在一個對象與它自身進行比較時才返回true

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM