【发布时间】:2020-12-03 18:07:55
【问题描述】:
根据 Java HashMap 文档,put 方法替换了之前包含的值(如果有):https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html#put-K-V-
将指定的值与此映射中的指定键相关联。如果 映射先前包含键的映射,旧值是 换了。
但是,文档并没有说明在存储新值时(现有)键会发生什么。现有密钥是否被替换?还是结果未定义?
考虑以下示例:
public class HashMapTest
{
private static class Key {
private String value;
private Boolean b;
private Key(String value, Boolean b) {
this.value = value;
this.b = b;
}
@Override
public int hashCode()
{
return value.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (obj instanceof Key)
{
return value.equals(((Key)obj).value);
}
return false;
}
@Override
public String toString()
{
return "(" + value.toString() + "-" + b + ")";
}
}
public static void main(String[] arg) {
Key key1 = new Key("foo", true);
Key key2 = new Key("foo", false);
HashMap<Key, Object> map = new HashMap<Key, Object>();
map.put(key1, 1L);
System.out.println("Print content of original map:");
for (Entry<Key, Object> entry : map.entrySet()) {
System.out.println("> " + entry.getKey() + " -> " + entry.getValue());
}
map.put(key2, 2L);
System.out.println();
System.out.println("Print content of updated map:");
for (Entry<Key, Object> entry : map.entrySet()) {
System.out.println("> " + entry.getKey() + " -> " + entry.getValue());
}
}
}
当我使用 Oracle jdk1.8.0_121 执行以下代码时,会产生以下输出:
Print content of original map:
> (foo-true) -> 1
Print content of updated map:
> (foo-true) -> 2
有证据表明(至少在我的 PC 上)现有密钥不会被替换。
这是预期/定义的行为(它在哪里定义?)还是只是所有可能结果中的一种?我可以指望这种行为在所有 Java 平台/版本中保持一致吗?
编辑:此问题与What happens when a duplicate key is put into a HashMap? 不重复。我问的是键(即当您使用多个键实例引用同一个逻辑键时),而不是值。
【问题讨论】:
-
“如果映射先前包含键的映射,则替换旧值。”所以值被替换,
(foo-true) -> 1旧值是1,替换后(foo-true) -> 2新值是2 -
是的,HashMap 使用 HashCode,根据 equals 和 hashcode 协定,检查键的唯一性。关键是您的 HashMap POV 中的 2 个键完全相同,因为您的 hashcode/equals 实现。所以不,没有更换钥匙,好地方!
-
您好 Anton Balaniuc,感谢您的回答。不过,我问的是关键,而不是价值。我完全同意最终的值一定是2(因为
key1和key2这两个键指的是同一个逻辑键),但是我在问自己,因为第二个键key2没有替换第一个键@987654334 @ 在 HashMap 中。