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.
A 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 BiMap
:
HashBiMap
is the most commonly used one, and works just as a regularHashMap
.EnumHashBiMap
is a specialBiMap
that can be useful when your keys are enums; just asEnumSet
, it can be faster than a regularHashBiMap
.EnumBiMap
is a special version of the above, useful when both your key and value are enums.ImmutableBiMap
is part of Guava’s immutable collections: it’s aBiMap
that cannot be modified once it has been created. ABuilder
class 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);