我无法弄清楚 HashMap 复制行为
我无法获取 HashMap 的单独副本。我的意思是,一旦我复制了原件,对其中一个进行更改不会改变另一个。
我有两个这种格式的 HashMap:
HashMap<String, List<String> one = new HashMap<String, List<String>();
HashMap<String, List<String> two = new HashMap<String, List<String>();
我调用下面的函数 (getTabSetDifferences) 传入一和二,正如预期的那样,如果存在一些差异,这些值将从 HashMap 中删除 它会与通过测试之前有所不同。
我希望它们保持不变,所以尝试传入:
getTabSetDifferences((HashMap)one.clone(), (HashMap)two.clone())
这仍然改变了原始值,所以我以相同的格式创建了两个以上的哈希图,并向它们克隆了一个和两个,我使用新的哈希图来传递 进去了,原来的还是改了。
然后我尝试:
HashMap<String, List<String>> holdOne = new HashMap<String, List<String>>();
holdOne.putAll(one);
HashMap<String, List<String>> Holdtwo = new HashMap<String, List<String>>();
holdTwo.putAll(two);
现在我可以做类似的事情:
holdTwo.remove(key);
并且原始的没有改变,但是如果我用holdOne和holdTwo调用该方法,它仍然会改变原始的一个和两个哈希图,它们不应该保留吗? 该方法正在工作,并找到我想要的差异,并返回。但我仍然需要原来的两个哈希图保持原样,但无论哪个 我这样称呼,对holdOne和holdTwo所做的任何更改都会改变原始内容。这是预期的行为吗?如果是这样,正确的方法是什么 获取未绑定的哈希图的副本。
getTabSetDifferences(holdOne, holdTwo);
public HashMap<String, List<String>> getTabSetDifferences(HashMap<String, List<String>> hmMain, HashMap<String, List<String>> hmSecond) {
HashMap<String, List<String>> hmDifferences = new HashMap<String, List<String>>();
for (Map.Entry<String, List<String>> entry : hmMain.entrySet()) {
if(hmSecond.containsKey(entry.getKey())) {
entry.getValue().removeAll(hmSecond.get(entry.getKey()));
if (entry.getValue().size() > 0)
hmDifferences.put(entry.getKey(), entry.getValue());
}
else {
hmDifferences.put(entry.getKey(), entry.getValue());
}
}
return hmDifferences;
}
I am having trouble getting a separate copy of my HashMaps. By that I mean, once I have made a copy of the original, making a change to one does not change the other.
I have two HashMaps in this format:
HashMap<String, List<String> one = new HashMap<String, List<String>();
HashMap<String, List<String> two = new HashMap<String, List<String>();
I call the following function below (getTabSetDifferences) passing in one and two, as expected if there are some differences, those values will be removed from the HashMap
and it'll be different than before it was passed in for the test.
I want them to remain unchanged, so tried passsing in:
getTabSetDifferences((HashMap)one.clone(), (HashMap)two.clone())
This still changed the originals, so i created two more hashmaps in the same format, and cloned one and two to them, I used the new hashmaps to pass
in, and the original was still changed.
I then tried:
HashMap<String, List<String>> holdOne = new HashMap<String, List<String>>();
holdOne.putAll(one);
HashMap<String, List<String>> Holdtwo = new HashMap<String, List<String>>();
holdTwo.putAll(two);
Now I can do something like:
holdTwo.remove(key);
and the original is not changed, but if i call the method with holdOne and holdTwo it still changes the original one and two hashmaps, shouldn't they remain?
The method is working, and finding the differences i want, and is returned. But I still need the original two hashmaps to be as they were, but no matter which
way I call, what ever changes are made to holdOne and holdTwo changes the originals. Is that the expected behavior? If so, what is the proper way
to get a copy of a hashmap that is not tied to it.
getTabSetDifferences(holdOne, holdTwo);
public HashMap<String, List<String>> getTabSetDifferences(HashMap<String, List<String>> hmMain, HashMap<String, List<String>> hmSecond) {
HashMap<String, List<String>> hmDifferences = new HashMap<String, List<String>>();
for (Map.Entry<String, List<String>> entry : hmMain.entrySet()) {
if(hmSecond.containsKey(entry.getKey())) {
entry.getValue().removeAll(hmSecond.get(entry.getKey()));
if (entry.getValue().size() > 0)
hmDifferences.put(entry.getKey(), entry.getValue());
}
else {
hmDifferences.put(entry.getKey(), entry.getValue());
}
}
return hmDifferences;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
克隆方法不进行深复制。
你有两个选择。
The clone method doesn't do a deep copy.
You have 2 options.
我怀疑您只是复制键/值。这不会创建列表的副本。
也许 Guava 的 MultiMap 就是您想要的?
I suspect you are only copying the keys/values. This will not create copies of the lists.
Perhaps Guava's MultiMap is what you want?
如果您将列表复制为列表(即在列表范围内复制它,而不是某些较低级别的实现),那么将看到指针行为......但是,如果您从一个列表复制到一个新列表,那么这些字符串对象是独立的。
Java 的克隆方法不应该期望它会返回对象的不同的深层副本 - 不变性不是克隆工作方式的核心概念。
我同意上面的评论:要么在像番石榴这样的库或谷歌集合中使用多重映射,要么只是非常小心地复制,并且只在原始级别复制,(永远不要复制集合并期望它是独立的)除非你已经明确地测试过这一点。
If you copy the list as a list (i.e. copy it at list scope, rather than some lower level implementation), then the pointer behavior will be seen.... However if you copy from one list into a new list, then those string objects are independant.
Java's clone method should not be use in expectation that it will return distinct , deep copies of an object - immutability is not a central concept to the way clone works.
I agree with the above comment : either use a multimap in a library like guava, or google collections, or simply be very careful about your copying, and only copy at the primitive levels, (don't ever copy a collection and expect it to be independent) unless you've tested this explicitly .