Embracing the Messiness in Search of Epic Solutions

Java: Performing 2-Key Lookup using HashBasedTable




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.



Leave a Reply