2012-01-28 28 views
8

我需要從java HashMap中獲取一個集合,而不需要稍後在集合中反映的地圖中的更改。我想使用Collection.toArray()來實現這一點,但它不工作。由此產生的對象[]也在改變(javadocs說,返回的數組將會是「安全的」,因爲這個集合沒有引用它)。任何簡單的方法來實現這一點?如何從java HashMap獲取不可變集合?

+0

我沒有清楚地理解你想要達到的目標。但是LinkedHashMap是你在找什麼? – batbaatar 2012-01-28 05:48:51

+0

不,插入順序不是我要找的。可以說我們有HashMap的。 Hashmap.values()會返回給我一個集合。現在HashMap中的任何更改都反映在這個集合中,這也是默認行爲。但是,我需要一個固定集合,其中映射的任何更改都不會反映出來 – sanre6 2012-01-28 05:54:37

+0

@ sanre6您的意思是更改* items *(objects)包含HashMap,偶然? – 2012-01-28 06:16:01

回答

9

無法通過單個API調用完成此操作,您需要使用深度克隆。當您更改原始文件時,克隆不會被更改。這個主題已經在SO之前討論過,參見How to clone ArrayList and also clone its contents?Deep clone utility recomendation

+0

我認爲這個答案可以擴展:「深層克隆」是什麼意思,這是如何防止修改或「共享引用」?一個鏈接可能是有用的... – 2012-01-28 06:14:51

+0

@Perception:感謝您的編輯。 – 2012-01-28 06:21:40

+0

Np,很好的答案。 – Perception 2012-01-28 06:27:22

8
+2

然而,這並沒有說明* contained *對象的可變性。 – 2012-01-28 06:15:28

+1

我相信谷歌收集Immutable Map是OP要找的東西。 @pst:通過閱讀文檔,我相信com.google.common.collect.ImmutableMap中包含的對象是不可變的。 – 2012-01-28 06:21:28

+1

我的理解也是一樣的 – 2012-01-28 06:24:35

2

您可以創建一個不可修改Map

+0

然而,這並沒有說明* contained *對象的可變性。 – 2012-01-28 06:14:09

+2

更不用說原始地圖中的更改會反映在副本中。 – Perception 2012-01-28 06:16:07

+0

我相信賈斯丁是對的。 'unmodifiableMap'方法將返回映射的只讀視圖,該視圖將反映對基本容器的任何更改,而sanre6並未指定所包含的對象應該是不可變的,只是映射應該是。 – Francois 2012-01-28 07:00:32

2

以下仍然有效,並說明所觀察到的問題(見上執行什麼樣的副本位)。然而,我沒有在上提供任何答案,如何執行深度複製。

相反,我的建議,是設計的對象是immutable,這完全避免了這個問題。根據我的經驗,對於大多數微不足道的對象(即不是「容器」的對象),它可以很好地工作,並且可以簡化代碼和推理。


從Javadoc文檔HashMap.values

返回包含在此映射中的值的Collection視圖。 收集是由地圖支持,所以更改地圖反映收集,反之亦然在...

也許這將有利於創造一個副本?

HashMap<K,V> map = ....; 
List<V> values = new ArrayList<V>(map.values()); 

這實質上是執行「現在分開」的shallow-copy。但是,淺拷貝,不包含所包含對象的克隆/副本。 (見βнɛƨнǤʋяʋиɢ的答案,如果deep-copy語義期望:這個問題本身似乎對此事有點含糊。)

快樂編碼

+0

我也一樣,這不起作用。這些更改也反映在新列表中 – sanre6 2012-01-28 06:24:01

+0

@ sanre6「變更」是指「對**中的對象**進行更改*」嗎? (與「收集*的變化」相反)。如果是這樣,請參閱淺/深層副本的鏈接,這些副本解釋觀察到的行爲,以及來自βнɛƨнǤʋяʋиɢ的答案。 – 2012-01-28 06:25:19

+0

耶正好改變到包含的對象 – sanre6 2012-01-28 06:27:54

0

蒙山HashMap.clone()創建原始地圖的淺表副本,然後檢索值從colleation那。這將在clone()調用時創建對原始映射中對象的新引用;包含對象本身內部的明顯變化仍將反映在複製的集合中。如果你想要這種行爲,你唯一的方法就是在你想要的集合中複製地圖對象。