1. Overview
In this tutorial, we’ll show how to use the Google Guava’s BiMap interface and its multiple implementations.
A BiMap (or “bidirectional map”) is a special kind of a map which maintains an inverse view of the map while ensuring that no duplicate values are present and a value can always be used safely to get the key back.
The basic implementation of BiMap is HashBiMap where internally it makes use of two Maps, one for the key to value mapping and the other for the value to key mapping.
2. Google Guava’s BiMap
Let’s have a look at how to use the BiMap class.
We’ll start by adding the Google Guava library dependency in the pom.xml:
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>21.0</version> </dependency>
The latest version of the dependency can be checked here.
3. Creating a BiMap
You can create an instance of BiMap in multiple ways as follows:
- If you are going to deal with a custom Java object, use the create method from the class HashBiMap:
BiMap<String, String> capitalCountryBiMap = HashBiMap.create();
- If we already have an existing map, you may create an instance of a BiMap using an overloaded version of the create method from a class HashBiMap:
Map<String, String> capitalCountryBiMap = new HashMap<>(); //... HashBiMap.create(capitalCountryBiMap);
- If you are going to deal with a key of type Enum, use the create method from the class EnumHashBiMap:
BiMap<MyEnum, String> operationStringBiMap = EnumHashBiMap.create(MyEnum.class);
- If you intend to create an immutable map, use the ImmutableBiMap class (which follows a builder pattern):
BiMap<String, String> capitalCountryBiMap = new ImmutableBiMap.Builder<>() .put("New Delhi", "India") .build();
4. Using the BiMap
Let’s start with a simple example showing the usage of BiMap, where we can get a key based on a value and a value based on a key:
@Test public void givenBiMap_whenQueryByValue_shouldReturnKey() { BiMap<String, String> capitalCountryBiMap = HashBiMap.create(); capitalCountryBiMap.put("New Delhi", "India"); capitalCountryBiMap.put("Washington, D.C.", "USA"); capitalCountryBiMap.put("Moscow", "Russia"); String keyFromBiMap = capitalCountryBiMap.inverse().get("Russia"); String valueFromBiMap = capitalCountryBiMap.get("Washington, D.C."); assertEquals("Moscow", keyFromBiMap); assertEquals("USA", valueFromBiMap); }
Note: the inverse method above returns the inverse view of the BiMap, which maps each of the BiMap’s values to its associated keys.
BiMap throws an IllegalArgumentException when we try to store a duplicate value twice.
Let’s see an example of the same:
@Test(expected = IllegalArgumentException.class) public void givenBiMap_whenSameValueIsPresent_shouldThrowException() { BiMap<String, String> capitalCountryBiMap = HashBiMap.create(); capitalCountryBiMap.put("Mumbai", "India"); capitalCountryBiMap.put("Washington, D.C.", "USA"); capitalCountryBiMap.put("Moscow", "Russia"); capitalCountryBiMap.put("New Delhi", "India"); }
If we wish to override the value already present in BiMap, we can make use of the forcePut method:
@Test public void givenSameValueIsPresent_whenForcePut_completesSuccessfully() { BiMap<String, String> capitalCountryBiMap = HashBiMap.create(); capitalCountryBiMap.put("Mumbai", "India"); capitalCountryBiMap.put("Washington, D.C.", "USA"); capitalCountryBiMap.put("Moscow", "Russia"); capitalCountryBiMap.forcePut("New Delhi", "India"); assertEquals("USA", capitalCountryBiMap.get("Washington, D.C.")); assertEquals("Washington, D.C.", capitalCountryBiMap.inverse().get("USA")); }
5. Conclusion
In this concise tutorial, we illustrated examples of using the BiMap in the Guava library. It is predominantly used to get a key based on the value from the map.
The implementation of these examples can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as is.