Google Guava: Bimaps
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")); // null
The 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
Next up, Multisets!
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





