Java HashMap:JVM中的错误还是我做错了?
在下面的代码中:-Java HashMap:JVM中的错误还是我做错了?,java,hashmap,Java,Hashmap,在下面的代码中:- 创建HashMap并添加一些元素 创建第二个HashMap,使用第一个HashMap的映射 修改第二个HashMap 第一个HashMap随?一起修改 public static void test(){ HashMap<Integer, ArrayList<Integer>> testData = new HashMap<Integer, ArrayList<Integer>> (); testData.put
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);
}
请在此处尝试:
我希望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);
正如在一篇评论中很好地解释的:
这可能很明显,但只是为了完整性:因为HashMap存储对象,而不是原语,所以您的映射存储对对象的引用。这就是为什么你需要从深层和浅层的角度来思考 另外,我还改进了您的示例代码:
- 在声明中使用接口类型,而不是实现类型
- 无需将
包装在数组.asList(…)
新数组列表(…)
- 在Java 7中使用菱形操作符
(因此,使用Java 7或更高版本,因为不再支持旧版本)
- 您正在制作原始
哈希映射的浅拷贝:
复制列表引用,然后复制它们的项
您需要自己进行深度复制:
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);
正如在一篇评论中很好地解释的:
这可能很明显,但只是为了完整性:因为HashMap存储对象,而不是原语,所以您的映射存储对对象的引用。这就是为什么你需要从深层和浅层的角度来思考
另外,我还改进了您的示例代码:
- 在声明中使用接口类型,而不是实现类型
- 无需将
数组.asList(…)
包装在新数组列表(…)
- 在Java 7中使用菱形操作符
(因此,使用Java 7或更高版本,因为不再支持旧版本)
java中的所有集合都包含对对象的引用。所以,当您从第二个映射修改列表时,它正在修改列表的同一个对象,java中的所有集合都将引用保留为对象。因此,当您从第二个映射修改列表时,它正在修改列表的同一对象是的,它是有意的。地图只存储参考,而不是对象。哦!这意味着两个贴图对象但包含相同的ArrayList?如何解决这个问题?是否需要手动创建阵列的另一个副本?克隆不是制作ArrayList的新副本。同样的问题持续存在,这是有意的。地图只存储参考,而不是对象。哦!这意味着两个贴图对象但包含相同的ArrayList?如何解决这个问题?是否需要手动创建阵列的另一个副本?克隆不是制作ArrayList的新副本。同样的问题持续存在这可能很明显,但只是为了完整性:因为HashMap存储对象,而不是原语,所以您的映射存储对对象的引用。这就是为什么你需要从深层和浅层的角度来思考。谢谢,我理解了。这对我来说有点不直观。所以Java中没有深度复制的速记?我的意思是必须有一个函数,它为对象和它所包含的对象进行复制谢谢@JonKiparsky,你说得太好了,我在我的答案中逐字逐句地包括了;-)@Java SDK中的MangatRai我不这么认为。在诸如Apache或Google的Guava之类的实用程序库中,可能有一些实用程序类可以简化这一过程。感谢您的建议……这可能是显而易见的,但只是为了完整性:因为HashMap存储对象,而不是原语,所以您的映射存储对对象的引用。这就是为什么你需要从深层和浅层的角度来思考。谢谢,我理解了。这对我来说有点不直观。所以Java中没有深度复制的速记?我的意思是必须有一个函数,它为对象和它所包含的对象进行复制谢谢@JonKiparsky,你说得太好了,我在我的答案中逐字逐句地包括了;-)@Java SDK中的MangatRai我不这么认为。在诸如Apache或Google的Guava之类的实用程序库中,可能有一些实用程序类可以简化这一过程。谢谢你的推荐。。。
{1=[777]}
{1=[777, 888]}