Guava Tips: Bimap
A rather common task is to model some relationship between two kinds of objects. Often you only need to go from a key to its value, and you will use a standard
Map, but sometimes you will have to go back from the “value” to the “key”. In cases like this, the common solution is to build two maps:
Map<A, B> a2b = new HashMap<>(); Map<B, A> b2a = new HashMap<>(); a2b.put(myA, myB); b2a.put(myB, myA);
However, this is quite cluttered and you can end up with subtle bug in case you forget to keep the two maps in sync, or fail to do so in case of concurrency.
Guava contains the very useful
BiMap interface and some common implementation to solve the problem. A
BiMap is a
Map that can be inverted, meaning that is able to give you an inverse map that goes from the values to the keys. This means that you cannot insert duplicated values, as well as duplicated keys, since otherwise the map would not be invertible.
The precise definition, taken from the javadoc, is:
A bimap (or “bidirectional map”) is a map that preserves the uniqueness of its values as well as that of its keys. This constraint enables bimaps to support an “inverse view”, which is another bimap containing the same entries as this bimap but with reversed keys and values.
BiMap’s inverse is a view: similarly to other Guava’s collections (such as
Multimap), this means that the result of
inverse is not a new map but rather an object that implements the correct interface, but uses the same underlying storage of the actual
BiMap: any change done to the inverse view will reflect in the
BiMap and viceversa.
Guava provides a few implementation of
HashBiMapis the most commonly used one, and works just as a regular
EnumHashBiMapis a special
BiMapthat can be useful when your keys are enums; just as
EnumSet, it can be faster than a regular
EnumBiMapis a special version of the above, useful when both your key and value are enums.
ImmutableBiMapis part of Guava’s immutable collections: it’s a
BiMapthat cannot be modified once it has been created. A
Builderclass is provided, similarly to the other immutable collections.
A quick example:
BiMap<A, B> bimap = HashBiMap.create(); bimap.put(myA, myB); assertEquals(bimap.inverse().get(myB), myA);