Guide to Guava Multimap

1. Overview

In this article, we will look at one of Map implementations from Google Guava library – Multimap. It is a collection that maps keys to values, similar to java.util.Map, but in which each key may be associated with multiple values.

2. Maven Dependency

First, let’s add a dependency:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>29.0-jre</version>
</dependency>

The latest version can be found here.

3. Multimap Implementation

In the case of Guava Multimap, if we add two values for the same key, the second value will not override the first value. Instead, we will have two values in the resulting map. Let’s look at a test case:

String key = "a-key";
Multimap<String, String> map = ArrayListMultimap.create();

map.put(key, "firstValue");
map.put(key, "secondValue");

assertEquals(2, map.size());

Printing the map‘s content will output:

{a-key=[firstValue, secondValue]}

When we will get values by key “a-key” we will get Collection<String> that contains “firstValue” and “secondValue” as a result:

Collection<String> values = map.get(key);

Printing values will output:

[firstValue, secondValue]

4. Compared to the Standard Map

Standard map from java.util package doesn’t give us the ability to assign multiple values to the same key. Let’s consider a simple case when we put() two values into a Map using the same key:

String key = "a-key";
Map<String, String> map = new LinkedHashMap<>();

map.put(key, "firstValue");
map.put(key, "secondValue");

assertEquals(1, map.size());

The resulting map has only one element (“secondValue”), because of a second put() operation that overrides the first value. Should we want to achieve the same behavior as with Guava’s Multimap, we would need to create a Map that has a List<String> as a value type:

String key = "a-key";
Map<String, List<String>> map = new LinkedHashMap<>();

List<String> values = map.get(key);
if(values == null) {
    values = new LinkedList<>();
    values.add("firstValue");
    values.add("secondValue");
 }

map.put(key, values);

assertEquals(1, map.size());

Obviously, it is not very convenient to use. And if we have such need in our code then Guava’s Multimap could be a better choice than java.util.Map.

One thing to notice here is that, although we have a list that has two elements in it, size() method returns 1. In Multimap, size() returns an actual number of values stored in a Map, but keySet().size() returns the number of distinct keys.

5. Pros of Multimap

Multimaps are commonly used in places where a Map<K, Collection<V>> would otherwise have appeared. The differences include:

  • There is no need to populate an empty collection before adding an entry with put()
  • The get() method never returns null, only an empty collection (we do not need to check against null like in Map<String, Collection<V>> test case)
  • A key is contained in the 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 (in Map<String, Collection<V>>, even if we remove all values from the collection, we still keep an empty Collection as a value, and this is unnecessary memory overhead)
  • The total entry values count is available as size()

6. Conclusion

This article shows how and when to use Guava Multimap. It compares it to standard java.util.Map and shows pros of Guava Multimap.

All these examples and code snippets can be found in the GitHub project – this is a Maven project, so it should be easy to import and run as it is.

Related posts:

Java Web Services – JAX-WS – SOAP
LinkedHashSet trong Java hoạt động như thế nào?
Java Program to Perform Addition Operation Using Bitwise Operators
ExecutorService – Waiting for Threads to Finish
Deploy a Spring Boot App to Azure
Lấy ngày giờ hiện tại trong Java
Java Program to Solve a Matching Problem for a Given Specific Case
Introduction to Apache Commons Text
The Difference Between Collection.stream().forEach() and Collection.forEach()
Getting Started with GraphQL and Spring Boot
How to Read HTTP Headers in Spring REST Controllers
Interface trong Java 8 – Default method và Static method
Java Program to Implement Lloyd’s Algorithm
Loại bỏ các phần tử trùng trong một ArrayList như thế nào trong Java 8?
Java 8 – Powerful Comparison with Lambdas
Mapping a Dynamic JSON Object with Jackson
Java Copy Constructor
Java Program to Implement AVL Tree
Java Program to Implement Selection Sort
Java Program to Find Location of a Point Placed in Three Dimensions Using K-D Trees
The “final” Keyword in Java
Java Program to Decode a Message Encoded Using Playfair Cipher
How to Count Duplicate Elements in Arraylist
Java Program to Find MST (Minimum Spanning Tree) using Kruskal’s Algorithm
Java Program to Implement Ternary Heap
Guide to the Java ArrayList
Java Program to Implement JobStateReasons API
Java Program to Check if a Given Binary Tree is an AVL Tree or Not
Hướng dẫn Java Design Pattern – Command
Tính đóng gói (Encapsulation) trong java
Java Program to Implement Gale Shapley Algorithm
Java Program to Represent Graph Using Adjacency Matrix