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):

 1private Map<String,List<Something>> stuff = new HashMap<String,List<Something>>();
 2
 3// ...
 4
 5public void add(String key, Something item) {
 6  if(!stuff.containsKey(key)) {
 7    stuff.put(key, new ArrayList<Something>());
 8  }
 9  stuff.get(key).add(item);
10}
11
12public List<Something> get(String key) {
13  return new ArrayList<Something>(stuff.get(key));
14}

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

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

 1private ListMultimap<String,Something> stuff = ArrayListMultimap.create();
 2
 3// ...
 4
 5public void add(String key, Something item) {
 6  stuff.put(key, item);
 7}
 8
 9public List<Something> get(String key) {
10  // might as well use the Lists convenience API while we're at it.
11  return Lists.newArrayList(stuff.get(key));
12}

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

 1// returns a composite of all values from all entries.
 2Collection<Something> allSomethings = stuff.values();
 3
 4// A more traditional map that can be edited.
 5Map<String, Collection<Something>> mapView = stuff.asMap();
 6
 7// remove an individual entry for a key.
 8boolean removed = stuff.remove(key, someVal);
 9
10// remove all for a key
11List<Something> removedSomethings = stuff.remove(key);
12
13// One for each value in the map. Updating this collection updates the map.
14Collection<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