繁体   English   中英

Java HashMap:JVM中的错误还是我做错了?

[英]Java HashMap: A Bug in JVM or I am doing wrong?

在下面的代码中:

  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]}

在这里尝试: Ideone.com上的代码

我期望testData和testData1彼此独立,但是似乎它们都引用同一个对象? 它打算用Java吗? 难道我做错了什么?

您正在对原始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或更高版本)

Java中的所有集合都保留对对象的引用。 因此,当您从第二张地图修改列表时,它正在修改列表的同一对象

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM