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 that 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>32.1.3-jre</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.
