2013-10-28 27 views
1

我遇到了LinkedHashSet及其包含方法的問題。 讓我把它總結給你。關於Java LinkedHashSet的問題包含方法

我有這個類C1有4個字符串屬性,它的各自的getter和setter以及eclipse默認給出的equals()和hashCode()方法。

然後我有另一個類C2具有1個屬性類型LinkedHashSet與getSet()方法來訪問它。

當我創建一個C1類(比如景物C1)的1個實例,並把它添加到C2類的一個實例C2,一切都很好...我做的:

C1 c1 = new C1("a", "b", "c", "d"); 
C2 c2 = new C2(); 
c2.getSet().add(c1); 

現在,如果我設置一個不同的值到c1的第一個屬性,用適當的set方法,然後我嘗試檢查c2.getSet()是否包含元素c1 ...但它總是返回false。 但是對象的哈希碼發生了變化,集合中的哈希碼也相同,顯然,contains方法中的equals測試失敗...

有沒有人知道這裏發生了什麼? 什麼可能是錯的? Equals和HashCode()?

由於提前, 歡呼

+0

如果hashCode改變了,HashSet將永遠不會找到它。閱讀文檔中的警告。 – SLaks

+0

你可以包括你的Equals和HashCode實現... –

+0

[更改存儲在基於散列的集合中的對象的hashCode]的可能重複(http://stackoverflow.com/questions/5174233/changing-hashcode-of-object-stored -in-hash-based-collection) – Holger

回答

1

將對象添加到散列集(或散列映射或任何使用散列查找對象的集合)時,集合類根據爲該對象計算的散列碼將對象放入「存儲桶」中。在此之後,您將更改對象的屬性,因爲在下次計算對象時,對象的哈希碼將有所不同。但是,該對象位於與舊哈希碼對應的位置/存儲區中。因此,當您嘗試使用更改後的屬性和哈希碼查找對象時,該集會查找錯誤的存儲桶並發現它爲空。 散列碼或等號方法沒有任何問題。你在這裏所犯的錯誤是這樣的:一旦對象被放入哈希集合或哈希映射中,決不要改變在哈希映射計算中使用的對象的字段。作爲最佳實踐,如果您知道要將它放入哈希集中,請將C1的這些屬性作爲final。

+0

非常感謝。實際上我明白HashMap是如何工作的,但是當涉及到一個Set的時候有點困惑。但由於HashSet使用內部的HashMap並使用set元素作爲鍵,所以這很有意義... – pnpo

0

LinkedHashSet集合將不會按照你的內部修改。 通過改變c1的內容,我認爲你改變了對象的hashCode。 因此,LinkedHashSet在您調用contains時無法檢索它。

+0

你可以查看http://en.wikipedia.org/wiki/Hash_table以獲得更多理解。 – Tyco