Master Google Guava’s Multimap to Boost Programming Efficiency

This article explains Guava's Multimap feature, covering its core one‑to‑many mapping capabilities, common methods, various implementations (ArrayListMultimap, HashMultimap, LinkedHashMultimap, TreeMultimap, immutable and synchronized versions), and provides concrete Java code examples and a social‑network scenario to help developers choose the right implementation.

Programmer1970
Programmer1970
Programmer1970
Master Google Guava’s Multimap to Boost Programming Efficiency

Core Features of Multimap

Multimap allows a key to map to multiple values, enabling one‑to‑many relationships such as a user with several email addresses or an order with multiple items. It also supports duplicate values, optional ordering, null keys/values, and provides rich views like asMap(), entries(), and values().

Common Methods

Typical usage requires adding the Guava dependency and importing the classes. Example code shows creating an ArrayListMultimap, adding entries with put and putAll, retrieving values with get, checking existence, removing entries, and using views such as keySet, values, entries, asMap, size, and isEmpty.

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Map;

public class MultimapExample {
    public static void main(String[] args) {
        Multimap<String, Integer> multimap = ArrayListMultimap.create();
        multimap.put("apple", 1);
        multimap.put("apple", 2);
        multimap.put("banana", 3);
        multimap.put("orange", 4);
        multimap.put("orange", 5);
        multimap.put("orange", 6);
        Map<String, Integer> moreFruits = Map.of("grape", 7, "grape", 8, "kiwi", 9);
        multimap.putAll(moreFruits);
        System.out.println("Apples: " + multimap.get("apple"));
        System.out.println("Contains key 'apple'? " + multimap.containsKey("apple"));
        System.out.println("Contains value 6? " + multimap.containsValue(6));
        boolean removed = multimap.remove("banana", 3);
        System.out.println("Removed banana=3? " + removed);
        multimap.removeAll("kiwi");
        System.out.println("Kiwis: " + multimap.get("kiwi"));
        System.out.println("Unique keys: " + multimap.keySet());
        System.out.println("All values: " + multimap.values());
        System.out.println("Entries: " + multimap.entries());
        System.out.println("As Map: " + multimap.asMap());
        System.out.println("Size of multimap: " + multimap.size());
        System.out.println("Is multimap empty? " + multimap.isEmpty());
    }
}

Choosing an Implementation

Guava offers several Multimap implementations, each with different performance and ordering characteristics.

ArrayListMultimap

Preserves insertion order of values and provides constant‑time get operations, but iteration over all entries may be slower in some scenarios.

HashMultimap

Fast key lookup, does not guarantee order, and disallows null keys or values.

LinkedHashMultimap

Combines fast key lookup with insertion‑order preservation, offering a good compromise.

TreeMultimap

Orders keys (and optionally values) using natural ordering or a supplied Comparator, useful for sorted traversals.

ImmutableSetMultimap / ImmutableListMultimap

Immutable variants are thread‑safe and efficient for read‑only scenarios because they cannot be modified after creation.

SynchronizedMultimap

Wraps any Multimap to make it thread‑safe; iteration must be performed inside a synchronized block to avoid concurrency issues.

ForwardingMultimap

Uses the decorator pattern, allowing custom behavior without modifying the underlying implementation. Example shows overriding putAll to log added values.

Practical Example

A simple social‑network simulation demonstrates using different Multimap types to store friends lists (ArrayListMultimap), likes (HashMultimap), messages (LinkedHashMultimap), and activity logs (TreeMultimap). The code adds data, prints collections, and removes a friend to illustrate typical operations.

import com.google.common.collect.*;
import java.util.*;

public class SocialNetwork {
    public static void main(String[] args) {
        ArrayListMultimap<String, String> friendsByUser = ArrayListMultimap.create();
        HashMultimap<String, String> likesByUser = HashMultimap.create();
        LinkedHashMultimap<String, String> messagesByUser = LinkedHashMultimap.create();
        TreeMultimap<Long, String> activityLog = TreeMultimap.create();

        friendsByUser.putAll("Alice", Arrays.asList("Bob", "Charlie", "David"));
        friendsByUser.putAll("Bob", Arrays.asList("Alice", "Charlie"));
        friendsByUser.put("Charlie", "David");

        likesByUser.put("Alice", "Bob's post");
        likesByUser.put("Alice", "Charlie's photo");
        likesByUser.put("Bob", "Charlie's photo");
        likesByUser.putAll("Charlie", Arrays.asList("Alice's status", "David's video"));

        messagesByUser.put("Alice", "Hi Bob!");
        messagesByUser.put("Alice", "How are you Charlie?");
        messagesByUser.put("Bob", "Charlie, where are you?");
        messagesByUser.putAll("Charlie", Arrays.asList("Here I am!", "Alice, check this out!"));

        activityLog.put(1L, "Alice added a new friend");
        activityLog.put(2L, "Bob liked a photo");
        activityLog.put(3L, "Charlie sent a message");

        System.out.println("Alice's friends: " + friendsByUser.get("Alice"));
        for (String user : likesByUser.keys()) {
            if (likesByUser.containsEntry(user, "Charlie's photo")) {
                System.out.println(user + " liked Charlie's photo");
            }
        }
        for (String message : messagesByUser.get("Alice")) {
            System.out.println("Alice said: " + message);
        }
        for (Map.Entry<Long, String> entry : activityLog.entries()) {
            System.out.println("Timestamp: " + entry.getKey() + ", Event: " + entry.getValue());
        }
        friendsByUser.remove("Alice", "Bob");
        System.out.println("Alice's friends after removing Bob: " + friendsByUser.get("Alice"));
    }
}

When selecting a Multimap, consider whether you need ordering, duplicate values, null handling, immutability, or thread safety, and choose the implementation that best matches those requirements.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaThread SafetyCollectionsImmutableMultimapGoogle Guava
Programmer1970
Written by

Programmer1970

Formerly called 'Code to 35'. Add our main WeChat ID to access a wealth of shared resources (algorithms, interview prep, tech stacks: Java, Python, Go, big data). We mainly share serious development techniques, focusing on output-driven input. Occasionally we post life snippets and gossip. Our aim is to attract precise traffic and test advertising opportunities.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.