Google Guava and Multimaps

It’s not uncommon in Java to build some sort of in-memory registry that contains a map with a list of items at each position. Often, these implementations look something like this (excluding concurrency details for brevity):

private Map<String,List<Something>> stuff = new HashMap<String,List<Something>>();

// ...

public void add(String key, Something item) {
  if(!stuff.containsKey(key)) {
    stuff.put(key, new ArrayList<Something>());

public List<Something> get(String key) {
  return new ArrayList<Something>(stuff.get(key));

Google’s Guava Libraries provide a few collections to help with this common case:, and the more specific variants ListMultimap, SetMultimap, and SortedSetMultimap.

The above code can be re-written with Guava like this:

private ListMultimap<String,Something> stuff = ArrayListMultimap.create();

// ...

public void add(String key, Something item) {
  stuff.put(key, item);

public List<Something> get(String key) {
  // might as well use the Lists convenience API while we're at it.
  return Lists.newArrayList(stuff.get(key));

The multi-map has a variety of fancy features that can be used as well. Here are just a few examples:

// returns a composite of all values from all entries.
Collection<Something> allSomethings = stuff.values();

// A more traditional map that can be edited.
Map<String, Collection<Something>> mapView = stuff.asMap();

// remove an individual entry for a key.
boolean removed = stuff.remove(key, someVal);

// remove all for a key
List<Something> removedSomethings = stuff.remove(key);

// One for each value in the map. Updating this collection updates the map.
Collection<Map.Entry<String,Something>> allEntries = stuff.entries();

All of the collections returned by the various API are views of the multimap. This can make it particularly easy to work with the map in a variety of ways. It does mean you should probably perform defensive copying anywhere you might be exposing these APIs (generally good practice in most cases, anyway).

comments powered by Disqus