tags:

views:

197

answers:

7

Is checking for key existence in HashMap always necessary?

I have a HashMap with say a 1000 entries and I am looking at improving the efficiency. If the HashMap is being accessed very frequently, then checking for the key existence at every access will lead to a large overhead. Instead if the key is not present and hence an exception occurs, I can catch the exception. (when I know that this will happen rarely). This will reduce accesses to the HashMap by half.

This might not be a good programming practice, but it will help me reduce the number of accesses. Or am I missing something here?

[Update] I do not have null values in the HashMap.

+13  A: 

Do you ever store a null value? If not, you can just do:

Foo value = map.get(key);
if (value != null) {
    ...
} else {
    // No such key
}

Otherwise, you could just check for existence if you get a null value returned:

Foo value = map.get(key);
if (value != null) {
    ...
} else {
    // Key might be present...
    if (map.containsKey(key)) {
       // Okay, there's a key but the value is null
    } else {
       // Definitely no such key
    }
}
Jon Skeet
A: 

I usually use the idiom

Object value = map.get(key);
if (value == null) {
    value = createValue(key);
    map.put(key, value);
}

This means you only hit the map twice if the key is missing

Jon Freedman
+3  A: 

Do you mean that you've got code like "if(map.containsKey(key)) doSomethingWith(map.get(key))" all over the place ? Then you should simply check whether map.get(key) returned null and that's it. By the way, HashMap doesn't throw exceptions for missing keys, it returns null instead. The only case where containsKey is needed is when you're storing null values, to distinguish between a null value and a missing value, but this is usually considered bad practice.

jkff
A: 

You won't gain anything by checking that the key exists. This is the code of HashMap:

@Override
public boolean containsKey(Object key) {
    Entry<K, V> m = getEntry(key);
    return m != null;
}

@Override
public V get(Object key) {
    Entry<K, V> m = getEntry(key);
    if (m != null) {
        return m.value;
    }
    return null;
}

Just check if the return value for get() is different from null.

This is the HashMap source code.


Resources :

Colin Hebert
@Donal Fellow, I didn't found the Sun's implementation, but the code is more or less the same (it's even more optimized for the `get()` to be precise). And I didn't say that it was _The_ implementation.
Colin Hebert
What is the point in showing one specific implementation of these methods?
jarnbjo
To explain that in most cases, checking that the key exists will take about the same time than getting the value. So it won't optimize anything to check the key actually exists before getting the value. I know it's a generalization but it can help to understand.
Colin Hebert
@Donal Fellow, I know, but like I said, I didn't find Sun's implementation online. You have to download it and accept the licence, and I don't really want to paste the "protected" code here. If you have a link to a good implementation visible online, I'll accept it gladly.
Colin Hebert
A good link is http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java (OpenJDK is very strongly derived from the Sun code) and it seems that I'm wrong. I was comparing the version for Java5 with Java6; they work differently in this area (but both are correct, as are the snippets you posted).
Donal Fellows
@Donal Fellows, thanks, I updated my post with it.
Colin Hebert
A: 
  1. If key class is your's make sure the hashCode() and equals() methods implemented.
  2. Basically the access to HashMap should be O(1) but with wrong hashCode method implementation it's become O(n), because value with same hash key will stored as Linked list.
Boris
A: 

Better way is to use containsKey method of HashMap . Tomorrow soembody will add null to the map , you should differentiate between key there and key has null value.

Suresh S
A: 

Just use containsKey for clarity, it's fast and keeps the code clean and readable. The whole point of HashMaps is that the key lookup is fast, just make sure the hashCode and equals are properly implemented.

Mikko Wilkman