【发布时间】:2012-07-05 15:25:47
【问题描述】:
我正在尝试迭代 HashMap 并将一些元素重写到另一个地图,但我遇到了以下问题:
@Test
public void test() {
Map<SubClass, String> map = new HashMap<SubClass,String>();
Map<SubClass, String> anotherMap = new HashMap<SubClass,String>();
map.put(new SubClass(), "10");
for(SubClass i : map.keySet()) {
System.out.println(i); // initial (because toString is implemented)
System.out.println(map.get(i)); // 10
// here it's ok...
i.name="another";
System.out.println(i); // another
System.out.println(map.get(i)); // null!
// but here it occurs that map.get(i) returns null!
anotherMap.put(i, map.get(i));
}
for(SubClass i : anotherMap.keySet()) {
System.out.println(i); // another
System.out.println(map.get(i)); // null!
}
}
// SubClass has String name; and hashCode and equals implemented
根据javadoc:
java.util.Map.keySet()返回此映射中包含的键的 Set 视图。该集合由地图支持,因此更改为 map 反映在集合中,反之亦然。如果在对集合进行迭代时修改了地图 进度(通过迭代器自己的删除操作除外),迭代的结果是 不明确的。该集合支持元素移除,即从地图中移除对应的映射, 通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作。它不支持 add 或 addAll 操作。
它说“对地图的更改会反映在集合中,反之亦然”。那么为什么它会以这种方式表现并且最重要的是:我如何克服它以使两个映射都只包含修改后的键和非空值?
更新: 我的朋友在 java 1.5.0.19 上做了这个测试(我有 1.7.0_03,同样发生在 1.5.0_21)并得到了正确的输出:
initial
10
another
10
更新2: 哦,他没有实现hashCode/equals,所以第一次更新是无关紧要的
【问题讨论】:
-
您正在更改密钥...这永远不会起作用,因为您对 map.get(i) 的第二次调用基于与第一个不同的密钥
-
那么这部分 javadoc 是什么意思:“对地图的更改反映在集合中,反之亦然”?
-
集合中的变化与集合中元素的变化不同