Next up on my tour of Guava, is the BiMap, another useful collection type. It’s pretty simple really, a BiMap is simply a two way map.
Inverting a Map
A normal java map is a set of keys and values, and you can look up values by key, very useful, eg lets say I wanted to create a (very rudimentary) British English to American English dictionary:
Map<String,String> britishToAmerican = Maps.newHashMap();
britishToAmerican.put('aubergine','egglant');
britishToAmerican.put('courgette','zucchini');
britishToAmerican.put('jam','jelly');But what if you want an American to British dictionary? Well you could write some code to invert the map:
// Generic method to reverse map.
public %lt;S,T> Map<T,S> getInverseMap(Map<S,T> map) {
Map<T,S> inverseMap = new HashMap<T,S>();
for(Entry<S,T> entry: map.entrySet()) {
inverseMap.put(entry.getValue(), entry.getKey());
}
return inverseMap;
}It’ll do the job, but there’s several complications you might need to think about.
- How do we handle duplicate values in the original map? At the moment they’ll be silently overwritten in the reverse map.
- What if we want to put a new entry in the reversed map? We’d also have to update the original map! This could get annoying.
BiMaps
Well, guess what? This is the sort of situation a BiMap is designed for! And here’s how you might use it.
BiMap<String,String> britishToAmerican = HashBiMap.create();
// Initialise and use just like a normal map
britishToAmerican.put('aubergine','egglant');
britishToAmerican.put('courgette','zucchini');
britishToAmerican.put('jam','jelly');
System.out.println(britishToAmerican.get('aubergine')); // eggplant
BiMap<String,String> americanToBritish = britishToAmerican.inverse();
System.out.println(americanToBritish.get('eggplant')); // aubergine
System.out.println(americanToBritish.get('zucchini')); // courgettePretty simple really, but there’s a few things to notice.
Enforcing uniqueness
Firstly the BiMap enforces uniqueness of it’s values, and will give you an illegal argument exception if you try to insert a duplicate value, ie
britishToAmerican.put('pudding','dessert');
britishToAmerican.put('sweet','dessert'); // IllegalArgumentException.If you need to add a values that has already been added there’s a forcePut method that will overwrite the entry with the duplicate value.
britishToAmerican.put('pudding','dessert');
britishToAmerican.forcePut('sweet','dessert'); // Overwrites the previous entry
System.out.println(britishToAmerican.get('sweet')); // dessert
System.out.println(britishToAmerican.get('pudding')); // nullThe inverse method
The other crucial thing to understand is the inverse method, this returns the inverse BiMap, ie the a map with the keys and values switched round.
Now this inverse map, isn’t just a new map, such as my earlier reverseMap method might have created. It’s actually a view of the of the original map. This means that any subsequent changes to the inverse method will affect the original map!
americanToBritish.put('potato chips','crisps');
System.out.println(britishToAmerican.containsKey('crisps')); // true
System.out.println(britishToAmerican.get('crisps')); // potato chipsSo that’s the BiMap, like I said pretty simple. As usual there are several implementations available, and as ever I recommend taking a look at the full API documentation:
http://guava-libraries.googlecode.com/svn/tags/release09/javadoc/com/google/common/collect/BiMap.html
Reference: Google Guava BiMaps from our JCG partner Tom Jefferys at the Tom’s Programming Blog blog.



