2014-12-06 56 views
0

在下面的代碼中: -Java HashMap:JVM中的錯誤或者我做錯了?

  1. 創建HashMap並添加一些元素。
  2. 創建第二個HashMap,採用第一個映射。
  3. 修改第二個HashMap。
  4. 第一個HashMap會被修改嗎?

    public static void test(){ 
        HashMap<Integer, ArrayList<Integer>> testData = new HashMap<Integer, ArrayList<Integer>>(); 
        testData.put(1, new ArrayList<Integer>(Arrays.asList(777))); 
        System.out.println(testData); 
        HashMap<Integer,ArrayList<Integer>> testData1 = new HashMap<Integer, ArrayList<Integer>> (testData); 
        testData1.get(1).add(888); 
        System.out.println(testData); 
    } 
    

輸出:

{1=[777]} 
{1=[777, 888]} 

嘗試在這裏:Code on Ideone.com

我預計雙方TESTDATA和testData1是相互獨立的,但似乎他們兩人指的是同一個對象?它是否用於Java?難道我做錯了什麼?

+1

是的,它是有意的。地圖只存儲*引用*,而不是對象。 – 2014-12-06 20:47:16

+0

哦!所以它意味着兩個地圖對象,但包含相同的ArrayList?如何解決這個問題? 我是否需要手動創建另一個數組副本?克隆沒有製作ArrayList的新副本。同樣的問題仍然存在 – 2014-12-06 20:49:05

回答

3

你正在做一個淺拷貝的原HashMap: 列表的引用被複制,那麼他們的項目。

你需要做一個深拷貝自己:

HashMap<Integer, List<Integer>> testData = new HashMap<>(); 
    testData.put(1, new ArrayList<>(Arrays.asList(777))); 

    HashMap<Integer, List<Integer>> testData = new HashMap<>(); 
    testData.put(1, Arrays.asList(777)); 

    HashMap<Integer, List<Integer>> testData2 = new HashMap<>(); 
    for (Map.Entry<Integer, List<Integer>> entry : testData.entrySet()) { 
     testData2.put(entry.getKey(), new ArrayList<>(entry.getValue())); 
    } 
    testData2.get(1).add(888); 
    System.out.println(testData); 
    System.out.println(testData2); 

此打印:

{1=[777]} 
{1=[777, 888]} 

由於@jon-kiparsky在評論很好地解釋說:

這可能很明顯,但只是爲了完整性:由於HashMap存儲對象,而不是基元,因此地圖存儲對對象的引用。這就是爲什麼你需要考慮深淺拷貝的原因。

而作爲一個側面說明,我也改善了您的示例代碼:

  • 在聲明而不是實現類型使用的接口類型
  • 無需包裝Arrays.asList(...)一個new ArrayList<>(...)
  • 使用內鑽石運算符<>在Java 7中(因此使用Java 7或更高版本,因爲不再支持舊版本)
+0

這可能很明顯,但僅僅爲了完整性:由於HashMap存儲對象而不是基元,因此地圖存儲對對象的引用。這就是爲什麼你需要考慮深淺拷貝的原因。 – 2014-12-06 20:54:23

+0

謝謝,我明白了。這對我來說有點不直觀。那麼在Java中沒有深度複製的簡寫? 我的意思是,它必須有一個函數,它爲對象和它包含的對象創建副本 – 2014-12-06 20:55:42

+0

謝謝@JonKiparsky,你說得那麼好我包括在我的答案中逐字;-) – janos 2014-12-06 20:58:51

0

java中的所有集合都將對象的引用保留。所以,當你從第二張地圖上修改列表時,它正在修改列表中的同一個對象

相關問題