[英]LinkedHashSet on objects without overridden hashCode() and equals()
[英]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()方法嗎?
這個對嗎 ?
當您的類不覆蓋hashCode()
和equals(Object o)
方法時,Java只使用對內存中對象的實際引用來計算值(即檢查它是否與該類的實例相同)。 這就是為什么你仍然得到兩個結果。
所有對象都有hashCode()和equals()。 如果未覆蓋它們,則使用默認實現。 默認行為是將所有對象視為不同,除非它們是同一個對象。
為了進行比較,即使您已覆蓋hashCode和equals,IdentityHashMap也會始終執行此操作。
它將使用對象類的equals和hashcode方法來查找值(因為Contact不會覆蓋equals和hashcode方法),所以是的。
默認情況下,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。
在這種情況下,將評估堆上的對象位置而不是值。
例如,對於兩個對象o1
和o2
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.