为什么HashMap包含比在Sun JDK中获取更慢的键?(太阳的jdk-1.6.0.17)

Ste*_*fan 8 java hashmap jdk1.6

为什么containsKey慢慢调用HashMap get呢?

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

小智 10

因为它有更多的工作,所以请参阅OpenJDK 7源代码.


请注意,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;
Run Code Online (Sandbox Code Playgroud)

虽然getEntry,来自containsKey,不分裂,getForNullKey并且在这里有额外的工作来检查空键案例(对于链中扫描的每个条目):

366               if (e.hash == hash &&
367                   ((k = e.key) == key || (key != null && key.equals(k))))
368                   return e;
Run Code Online (Sandbox Code Playgroud)

另外,containsKey还有附加的条件和方法调用(注意getEntry,如果存在所述键,则返回一个Entry对象,即使存储的值是null):

352           return getEntry(key) != null;
Run Code Online (Sandbox Code Playgroud)

我认为可以说,containsKey从"性能"方面来说,从一个专门的形式(以较少的干代码为代价),或者getEntry可以跟随get早期空键检查的引导,将会受益.另一方面,可能有人认为get应该用getEntry;-) 来写

快乐的编码.

  • 这样做是为了支持空值.(`map.containsKey(key)`不等于`map.get(key)== null`.) (4认同)