Java: Performing 2-Key Lookup using HashBasedTable

PROBLEM

HashMap is great to perform a simple lookup, for example:-

Map<String, String> map = new HashMap<String, String>();
map.put("key", "mike");

String value = map.get("key"); // "mike"

However, what if we need 2 keys to lookup a value? For example, we need “key1” + “key2” in order to lookup “mike”.

SOLUTION 1: Create combo key

You can combine the keys to create a unique key:-

Map<String, String> map = new HashMap<String, String>();
map.put("key1|key2", "mike");

String value = map.get("key1|key2"); // "mike"

Assuming if the keys are just characters, this works fine. However, this solution might not work too well if the keys are objects, like Person object, etc.

SOLUTION 2: Create key as an object

In this solution, we leverage Apache Commons’ MultiKey to create the combo key:-

Map<MultiKey, String> map = new HashMap<MultiKey, String>();
map.put(new MultiKey("key1", "key2"), "mike");

String value = map.get(new MultiKey("key1", "key2")); // "mike"

This solution works a little better than the first solution, but the code looks just plain ugly to read.

SOLUTION 3: Using Map of Map

In this solution, we use Map of Map to accomplish the 2-key lookup:-

Map<String, Map<String, String>> map = new HashMap<String, Map<String, String>>();

Map<String, String> innnerMap = new HashMap<String, String>();
innnerMap.put("key2", "mike");

map.put("key1", innnerMap);

String value = map.get("key1").get("key2"); // "mike"

This solution obviously offers tons of flexibility, but it is shit difficult to read… and sadly, I myself implemented something like this in the past. In my opinion, this solution is too complicated for what we are trying to achieve here. We also have to worry about whether map.get(firstKey) will return null, which may cause NullPointerException if we chain the call to lookup the second key.

SOLUTION 4: Using HashBasedTable

The most elegant solution in my opinion is to utilize Google Guava’s HashBasedTable:-

HashBasedTable<String, String, String> hashBasedTable = HashBasedTable.create();
hashBasedTable.put("key1", "key2", "mike");

String value = hashBasedTable.get("key1", "key2"); // "mike"

This is probably the cleanest solution to perform 2-key lookup. Based on the documentation, HashBasedTable itself is using Map of Map under the cover.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s