Key existence check in HashMap

Viewed 577870

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.

11 Answers

You can also use the computeIfAbsent() method in the HashMap class.

In the following example, map stores a list of transactions (integers) that are applied to the key (the name of the bank account). To add 2 transactions of 100 and 200 to checking_account you can write:

HashMap<String, ArrayList<Integer>> map = new HashMap<>();
map.computeIfAbsent("checking_account", key -> new ArrayList<>())
   .add(100)
   .add(200);

This way you don't have to check to see if the key checking_account exists or not.

  • If it does not exist, one will be created and returned by the lambda expression.
  • If it exists, then the value for the key will be returned by computeIfAbsent().

Really elegant!

The Jon Skeet answer addresses well the two scenarios (map with null value and not null value) in an efficient way.

About the number entries and the efficiency concern, I would like add something.

I have a HashMap with say a 1.000 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.

A map with 1.000 entries is not a huge map.
As well as a map with 5.000 or 10.000 entries.
Map are designed to make fast retrieval with such dimensions.

Now, it assumes that hashCode() of the map keys provides a good distribution.

If you may use an Integer as key type, do it.
Its hashCode() method is very efficient since the collisions are not possible for unique int values :

public final class Integer extends Number implements Comparable<Integer> {
    ...
    @Override
    public int hashCode() {
        return Integer.hashCode(value);
    }

    public static int hashCode(int value) {
        return value;
    }
    ...
}

If for the key, you have to use another built-in type as String for example that is often used in Map, you may have some collisions but from 1 thousand to some thousands of objects in the Map, you should have very few of it as the String.hashCode() method provides a good distribution.

If you use a custom type, override hashCode() and equals() correctly and ensure overall that hashCode() provides a fair distribution.
You may refer to the item 9 of Java Effective refers it.
Here's a post that details the way.

Since java 1.8, you can simply use:

var item = mapObject.getOrDefault(key, null);
if(item != null)
Related