2012-12-19 33 views
6

我只是想確保我的代碼是安全使用Integer對象作爲關鍵。這裏有一個簡單的例子:帶有整數鍵的Java Map:如何比較鍵?

Integer int1 = new Integer(1337); 
Integer int2 = new Integer(1337); 

if (int1 == int2) { 
    System.out.println("true"); 
} else { 
    System.out.println("false"); 
} 

if (int1.equals(int2)) { 
    System.out.println("true"); 
} else { 
    System.out.println("false"); 
} 

Map<Integer, Object> map = new HashMap<Integer, Object>(); 
map.put(int1, null); 
map.put(int2, null); 

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

代碼將輸出

false 
true 
1 

這就是我所期待的,引用不同,但它們彼此相等。現在我對Map的行爲很感興趣。

  • 能夠保證所有的像地圖或設置集合將通過其內容的按鍵比較,而不是他們的參考?
  • 還是取決於實際的實施,如HashMap
+0

@close:這不是重複 - 其他帖子處理「等於==」的問題,而這個問題是關於Integer在集合中的表現如何?這就是爲什麼底部有彈痕點。我問:收藏如何處理。 – Scolytus

回答

7

方法equals被調用,因此它是被比較的內容。

至於你上面的兩個問題:

鑑於兩個對象o1o2(爲了簡化,我們假設o1!=nullo2!=null),搭扣地圖,最終,有以確定它們是否具有相同的值。 (最終,因爲HaspMap也檢查o1o2是否具有相同的散列值,但這在您的問題的上下文中並不重要)。它通過調用方法equals()來完成此操作。只要o1.equals(o2)是錯誤的,這兩個對象被HashMap視爲兩個不同的鍵。

HashSet也調用equals()來確定元素是否已經包含在集合中,請參閱http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add%28E%29

TreeMap另一方面,必須比較兩個對象,並確定它們是否相等,或者哪一個更大。它通過調用compareTo()來實現。因此,這是重要的o1.compareTo(o2)的返回值(或者,如果您使用構造函數http://docs.oracle.com/javase/6/docs/api/java/util/TreeMap.html#TreeMap%28java.util.Comparator%29創建了樹圖,則使用比較器)。因此

什麼保證的是,在HashMapHashSet,所述方法equals()用於分辨的對象,並且在TreeMap,該方法compareTo()

+0

它實際上取決於equals方法的實現。無論如何,你可以在equals方法中通過引用進行比較。 – nhahtdh

+0

hashcode()方法如何。儘管equals返回true,並且如果hashcode()值不同,仍然這兩個鍵是相同的。 –

+0

@VallabhPatade:hashCode'的'合同:'如果兩個對象根據equals(Object)方法是相等的,result.'你可以自由地打破然後調用在每個兩個對象的hashCode方法必須產生相同的整數合同,但應用程序依賴於它會中斷。 – nhahtdh

3

如果你打開implementationjava.util.AbstractMap你可以看到,使用Object#equals方法檢查鍵和值方程無處不在。實際內部地圖比較取決於Object#equals方法的鍵/值執行。

0

它實際上取決於equals()實現您指定MapK /關鍵的。

嘗試做同樣與Map<Object,String>,看看會發生什麼(提示:爲Object的等於他們實際上必須是同一個對象)

乾杯

1

這裏Integer是Waraper final類,這是覆蓋equals()方法,所以它只會比較內容。

所以,如果使用整數任何包裝類存在Map

沒有問題的假設,如果你想使用Custome類關鍵你需要重寫equals() and hashcode()方法,以避免在Map

+1

通常不是真的,你可以輕鬆擁有它覆蓋'的equals()'仍然對測試對象的平等,而不是內容相等final類... –

+0

Integer類是final類,但它有僅限於內容。這意味着我們不能重寫這個Integer類方法來改變行爲。 – NPKR

+0

也許你應該提到的是地圖中一般把equals方法來確定鍵的平等 - 這就是我要求;) – Scolytus

0

重複前比較兩個不同對象(引用) - > false。

第二比較(等於)這些對象的值 - >真

的Hashmap使用equals和對象的hascode方法來確定唯一的密鑰。所以你有兩次插入相同的密鑰導致剩下一個元素。第二個。看看Map#put javadoc看看發生了什麼。

+0

這不正是我一直在問,但javadoc的給了我一個線索。重要的部分在.containsKey()指定使用的地方.equals() – Scolytus

0

在散列映射的情況下,密鑰使用equals進行比較()和散列碼()方法。

上例中,hashcode()和equals()都在Integer類中重寫。當HashMap對兩個鍵進行比較時,首先獲取該對象的hashcode(),然後調用該對象的equals方法和具有相同散列碼值的鍵。

+0

這不是我的問題的確切答案。 – Scolytus

+0

告訴我我不清楚的地方嗎? –

+0

這不是我的問題的答案。不過,看起來我的問題並不容易理解。 (至少人們不明白這一點)。我的主要興趣是問題結尾的兩個重點,幾乎沒有人回答。無論如何,由於所有答案的總和,我已經知道了。所有的地圖都應該調用equals()來進行密鑰比較。也許我會編輯這個問題來清理它,我認爲更多的上下文會很好。 – Scolytus

6

Q1: - 是保證像地圖或設置集合將通過其內容的按鍵比較,而不是他們的參考?

A1: - 集合號,地圖和set接口。他們只保證可能方法的合同。

Q2: - 取決於它在實際應用中,像HashMap的?

A2:是的。班級如何處理比較是開發者的決定。

的HashMap用兩兩件事來分配自己的對象

首先 - 是Object#hashCode(),是用於計算指數。

第二 - 是Object#equals(),那就是用哈希碰撞的地方。

0

將項目放入HashMap(以及擴展名爲HashSet)時,使用hashCode(由簡單的線性函數進行轉換)來確定項目應放置在內部集合中的位置。

然後在確定的位置使用(o1 == o2 || o1.equals(o2))搜索一個相同的對象(在所有存儲的項目中),如果引用不同,則調用#equals函數,這是簡化#equals調用的性能改進。如果找到相同的項目,則將其分配的值替換爲新的項目,如果不是,則將新項目簡單地添加到內部收集中。