如果条目已存在,则Map保留哪个密钥实例?

时间:2014-03-29 02:23:54

标签: java collections map

考虑以下地图:

Map<Foo,Bar> fooBarMap = new Map<Foo,Bar>();

以下两个Foo,foo1和foo2实例:

foo1 != foo2
foo1.equals(foo2)

(即它们是分开但等同的)。现在,考虑以下插入:

fooBarMap.put(foo1,bar1);
fooBarMap.put(foo2,bar2);

问题:保留哪个密钥? foo2会替换foo1吗?

换句话说,两次使用相同的密钥更新密钥和值,还是只更新值?

(如果你想知道我为什么要问,那是因为我正在使用WeakHashMap并且必须确保我不会过早地发布引用。)

提前致谢...

3 个答案:

答案 0 :(得分:2)

此示例代码:

    final Map<String, String> map = new HashMap<>();
    final String foo1 = new String("foo");
    final String foo2 = new String("foo");
    map.put(foo1, "bar");
    map.put(foo2, "bar");
    System.out.println(map.keySet().iterator().next() == foo1);
    System.out.println(map.keySet().iterator().next() == foo2);

打印:

true
false

似乎很合乎逻辑,因为.keySet()的{​​{1}}是Map,而Set不会替换已有的值。 javadoc for Set's .add()表示:

  

如果指定的元素尚不存在,则将其添加到此集合中(可选操作)。

请注意&#34;可选操作&#34;是因为如果Set实现不支持添加,文档也会说UnsupportedOperationException被抛出。

答案 1 :(得分:1)

这取决于Map的实现。我见过的大多数实现都会保留第一个密钥,因为逻辑往往是“通过密钥查找条目,如果存在,则更新条目中的值”,即它不会覆盖密钥参考文献

答案 2 :(得分:1)

HashMap的官方Sun / Oracle实现执行以下操作。

使用此语句序列:

map.put(foo1, "bar1");
map.put(foo2, "bar2");

如果foo2和foo1具有相同的hashCode(),并且(foo2 == foo1)或(foo2.equals(foo1)),那么:

  • 将保留现有密钥(foo1),但
  • 其映射值将更改为“bar2”

除了:(foo2 == foo1)并不暗示(foo2.equals(foo1)),因为并非所有equals()实现都执行'=='测试 - 即使它们应该。另外,(foo2.equals(foo1))并不暗示(foo1.equals(foo2))!