为什么在HashMap上调用containsKeyget慢?

测试:http://ideone.com/QsWXF(相差> 15%,在sun-jdk-1.6.0.17上运行)

最佳答案

因为它确实可以做更多的工作,所以请参阅the OpenJDK 7 source

请注意,containsKey调用getEntry,而get直接“进行魔术查找”。我不知道为什么要用这种方法,并且对getForNullKey的使用/不使用感到更加困惑:参见John B和Ted Hopps的评论。
get对空键进行了早期的代码拆分(请注意,如果条目不存在或存储了空值,则get将返回null):

315           if (key == null)
316               return getForNullKey();
...
322               if (e.hash == hash &&
                      ((k = e.key) == key || key.equals(k)))
323                   return e.value;

虽然从getEntry调用的containsKey不会拆分为getForNullKey,但是这里还有其他工作来检查空键大小写(针对链中扫描的每个条目):
366               if (e.hash == hash &&
367                   ((k = e.key) == key || (key != null && key.equals(k))))
368                   return e;

另外,containsKey具有附加的条件和方法调用(请注意,即使存储的值为getEntry,即使存在上述键,null也会返回Entry对象):
352           return getEntry(key) != null;

我想可以认为containsKey从“性能”方面受益于具有专门的格式(以减少DRY代码为代价),或者getEntry可以跟随get的开头进行早期的空键检查..另一方面,可能有人争辩说get应该用getEntry来写;-)

快乐的编码。

10-06 10:52