How to Use Guava BiMap for Inverse Map Lookup
A BiMap is useful in scenarios where you need to look up data in both directions.
For example, if you have a mapping between employee IDs and names, and you want to quickly retrieve an employee’s ID based on their name or vice versa, a BiMap can provide this functionality.
Guava provides an implementation of the BiMap interface called HashBiMap. Let’s see you can use it.
Adding Guava to our Project
If you’re using Maven, add the following dependency to the pom.xml file:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version> <!-- Check for the latest version -->
</dependency>
For Gradle, add this to the build.gradle:
implementation 'com.google.guava:guava:31.0.1-jre' // Check for the latest version
Create a BiMap and Get the Ieverse Map
@Test
public void testBiMap() {
BiMap<Integer, String> empIDNameMap = HashBiMap.create();
empIDNameMap.put(1, "Alice");
empIDNameMap.put(2, "Tom");
Assertions.assertEquals(2, empIDNameMap.inverse().get("Tom"));
}
By calling inverse()
method on biMap, we can get the employee id by employee name.
null as Inverse BiMap Key
BiMap also allows null
value as key of inverse map.
@Test
public void testNullInverseKeyBiMap() {
BiMap<Integer, String> empIDNameMap = HashBiMap.create();
empIDNameMap.put(1, "Alice");
empIDNameMap.put(2, null);
Assertions.assertEquals(2, empIDNameMap.inverse().get(null));
}
Add Entries to BiMap
Adding entries to empIdNameMap
will also add a reverse entry to inverseMap
, and entries added to inverseMap
will also change the original empIdNameMap
.
@Test
public void testAddEntryToBiMap() {
BiMap<Integer, String> empIDNameMap = HashBiMap.create();
empIDNameMap.put(1, "Alice");
BiMap<String, Integer> inverseMap = empIDNameMap.inverse();
empIDNameMap.put(4, "Joey");
Assertions.assertEquals(4, inverseMap.get("Joey"));
}
@Test
public void testAddEntryToInverseBiMap() {
BiMap<Integer, String> empIDNameMap = HashBiMap.create();
empIDNameMap.put(1, "Alice");
BiMap<String, Integer> inverseMap = empIDNameMap.inverse();
inverseMap.put("Tom", 3);
Assertions.assertEquals("Tom", empIDNameMap.get(3));
}
Remove Entries from BiMap
Removing entries from empIdNameMap
will also remove the corresponding reverse entry from inverseMap
, and entries removed from inverseMap
will also change the original empIdNameMap
.
@Test
public void testRemoveEntryFromBiMap() {
BiMap<Integer, String> empIDNameMap = HashBiMap.create();
empIDNameMap.put(1, "Alice");
BiMap<String, Integer> inverseMap = empIDNameMap.inverse();
empIDNameMap.remove(1);
Assertions.assertNull(inverseMap.get("Alice"));
}
@Test
public void testRemoveEntryFromInverseBiMap() {
BiMap<Integer, String> empIDNameMap = HashBiMap.create();
empIDNameMap.put(1, "Alice");
BiMap<String, Integer> inverseMap = empIDNameMap.inverse();
inverseMap.remove("Alice");
Assertions.assertNull(empIDNameMap.get(1));
}
Avoid Duplicate Values
BiMap ensures unique mappings in both directions, if you try to put a duplicate value, it will throw an IllegalArgumentException.
@Test
public void testDuplicateInverseKeys() {
BiMap<Integer, String> empIDNameMap = HashBiMap.create();
assertThrows(IllegalArgumentException.class,
() -> {
empIDNameMap.put(1, "Alice");
empIDNameMap.put(2, "Alice");
});
}