Google Guava’s Multimap Class in Java

Google Guava’s Multimap interface allows the mapping of a single key to multiple values in Java, unlike java.util.Map where a key can only be mapped to a single value. In this post, we will see how to use Guava’s Multimap in Java and also discuss its advantages over standard map implementation.


 

A Multimap is a collection that maps keys to values, similar to Map, but each key may be associated with multiple values. In the previous post, we have seen how to implement our own Multimap class in Java using a Map and a Collection. Multimap implementation is also provided by many third party libraries such as Guava and Apache Commons. Let’s discuss various utility methods provided by Guava’s Multimap interface –

 

1. Basic Usage: Initializer, put(), get() methods

We know that if we put two values into the java.util.Map using the same key, the second put operation will override the value set by the first put() operation.

 
Above behavior enforces the map’s key to associate with only one value, which is sometimes undesirable. Guava’s Multimap, on the other hand, allows to add one or more values for the same key by maintaining a Collection of values. Any subsequent put() operations on a key will not override the values set by the previous put() operations on that key.

 
Please note that few multimap implementations like ArrayListMultimap allow duplicate key-value pairs, and some implementations like ForwardingSetMultimap doesn’t allow duplicates in it. This basically depends on the underlying data structure, for example, a List supports duplicates whereas a Set doesn’t. Also, instead of using the Multimap interface directly, one should prefer using the sub-interfaces ListMultimap and SetMultimap.

 
The get() method of Guava’s Multimap returns a view of collection of the values associated with specified key in the multimap. It returns an empty collection when the key is not present in the map. Since a view is returned, the underlying multimap gets updated on doing any changes to the returned collection, and vice versa.

 
Below is simple Java program to demonstrate Guava’s MultiMap interface in Java. It uses ArrayListMultimap implementation of ListMultimap that internally uses an ArrayList to store the values for a given key.

 

Download   Run Code

Output:

John: [Adams, Tyler, Kennedy]
George: [Washington, Bush]

 

2. Converting Multimap<K,V> to Map<K, Collection<V>>

Guava’s Multimap maintains flattened collection of key-value pairs like <K,V>. We can convert it to a map where each distinct key K is mapped to a non-empty collections of that key’s associated values like <K,Collection<V>> using asMap() method. Please note that the returned map Map<K,Collection<V>> is backed by the underlying multimap.

 

Download   Run Code

Output:

John: [Adams, Tyler, Kennedy]
John: [Adams, Tyler, Kennedy]

 

3. Iterate over the Multimap

Guava’s Multimap provides keySet(), entries(), values(), keys() methods which are similar to the corresponding view collections of Map.

 
Input multimap: (for below functions)

George –> Washington, Bush
Zachary –> Taylor
John –> Adams, Tyler, Kennedy
Grover –> Cleveland

 

3.1. keySet()

 

Download   Run Code

Output:

George: [Washington, Bush]
Zachary: [Taylor]
John: [Adams, Tyler, Kennedy]
Grover: [Cleveland]

 

3.2. entries()

 

Download   Run Code

Output:

George: Washington
George: Bush
Zachary: Taylor
John: Adams
John: Tyler
John: Kennedy
Grover: Cleveland

 

3.3. keys() and values()

 

Download   Run Code

Output:

[George x 2, Zachary, John x 3, Grover]
[Washington, Bush, Taylor, Adams, Tyler, Kennedy, Cleveland]

 

4. Remove/Replace existing keys/values in the Multimap

Guava’s Multimap provides remove() method that removes a single key-value pair from the multimap that matches with the specified key-value pair. It returns true if the pair is removed, else it returns false if no such pair is found.

Guava’s Multimap also has removeAll() method that removes all values associated with the specified key and returns the collection of removed values.

For replacing the existing values for a particular key, Guava provides replaceValues() method. If no values were previously associated with the key, replaceValues() will create the mapping between the specified key and value. It returns the collection of replaced values or empty collection if no value are replaced.

 

Download   Run Code

Output:

– – – – – – – – – – – – Before – – – – – – – – – – – –

{George=[Washington, Bush], Zachary=[Taylor], John=[Adams, Tyler, Kennedy]}

– – – – – – – – – – – – After – – – – – – – – – – – –

{Zachar=[T.], Obama=[Barak], Zachary=[Taylor], John=[Adams, Kennedy]}

 

5. Size() of the multimap

We can use size() method to find out the number of key-value pairs contained in the multimap. Please note that this method does not return the number of distinct keys in the multimap. To get the number of distinct keys, consider using keySet().size() or asMap().size().

 

6. Finding key/values in the multimap

Guava provides three methods, namely containsKey(), containsValue() and containsEntry() to check if the multimap contains at least one key-value pair with the specified key, specified value and the specified key-value pair respectively.

 

Download   Run Code

Output:

Multimap contains “John” key
Multimap contains “Kennedy” value
Multimap contains the specified mapping

 

7. Immutable Multimap in Guava

Guava’s Multimap interface has three immutable implementations – ImmutableMultimap, ImmutableListMultimap and ImmutableSetMultimap, which should always be preferred over the mutable implementations.

 

Download   Run Code

Output:

John: [Adams, Tyler, Kennedy]
java.lang.UnsupportedOperationException thrown

 

Pros of Guava’s Multimap over java.util.Map

Guava’s Multimap is commonly used in places where a Map<K, Collection<V>> would otherwise have appeared. The differences include:

  1. In Guava’s Multimap, there is no need to populate an empty collection before adding an entry with put().
     
  2. The get() method of Guava’s Multimap returns an empty collection when containsKey(key) is false, unlike get() method of java.util.Map which returns a null.
     
  3. Unlike java.util.Map, a key is contained in the Guava’s Multimap if and only if it maps to at least one value. Any operation that causes a key to has zero associated values, has the effect of removing that key from the Multimap.
     
  4. The size() method of Guava’s Multimap returns the exact number of key-value pairs contained in it. The size() method of java.util.Map, on the other hand, returns the number of distinct keys present in it.

 
References: Multimap (Guava: Google Core Libraries for Java 23.0 API)

 
Thanks for reading.




Please use ideone or C++ Shell or any other online compiler link to post code in comments.
Like us? Please spread the word and help us grow. Happy coding 🙂
 





Leave a Reply

Notify of
avatar
wpDiscuz