Search code examples
javahashmapjava-6

Why is HashMap containsKey slower than get in Sun JDK? (sun-jdk-1.6.0.17)


Why is calling containsKey on a HashMap slower then get?

Test: http://ideone.com/QsWXF (>15% difference, run on sun-jdk-1.6.0.17)


Solution

  • Because it does [ever so slightly] more work, see the OpenJDK 7 source.


    Note that containsKey calls getEntry while get directly "does the magic lookup". I do not know why it was done this way, and am further puzzled by the use/not use of getForNullKey: See John B's and Ted Hopps's comments as to why this is done.

    get has an early code split for a null-key (note that get will return null if the entry doesn't exist or existed with a null value stored):

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

    While getEntry, called from containsKey, does not split to getForNullKey and there is additional work here to check for the null-key case (for each Entry scanned in the chain):

    366               if (e.hash == hash &&
    367                   ((k = e.key) == key || (key != null && key.equals(k))))
    368                   return e;
    

    Also, containsKey has the additional conditional and method call (note that getEntry will return an Entry object, if said key exists, even if the stored value is null):

    352           return getEntry(key) != null;
    

    I suppose it could be argued that containsKey would benefit - in terms of "performance" - from having a specialized form (at the expense of less-DRY code), or that getEntry could follow the lead of get with an early null-key check .. on the other-hand, it might be argued that get should be written in terms of getEntry ;-)

    Happy coding.