In part one, two and three of this blog series we have covered the Google Guava library and the Google Collections library, and how you as a Java developer can benefit from using these libraries to reduce the amount of boilerplate code in your projects. In the final blog post of this series I will walk you through the über collection “Multimap” – which you will all fall in love with and become addicted to;) We will take a look at how you can use Google Collections to do validation with the use of Preconditions, but first, let’s take a look at how we can perform Set and Map operations such as intersections, union and difference.
Set intersections, unions and map operations
Something that tends to be quite the hassle (and messy to write) is to do stuff like intersections, unions or diff on two sets. You often end up having to loop over the sets and well, you don’t want to write that code over and over again. With the Sets class provided by Google Collections, you get stuff like this out of the box (and completely free!
HashSet setA = newHashSet(1, 2, 3, 4, 5);
HashSet setB = newHashSet(4, 5, 6, 7, 8);
SetView union = Sets.union(setA, setB);
System.out.println("union:");
for (Integer integer : union)
System.out.println(integer);
SetView difference = Sets.difference(setA, setB);
System.out.println("difference:");
for (Integer integer : difference)
System.out.println(integer);
SetView intersection = Sets.intersection(setA, setB);
System.out.println("intersection:");
for (Integer integer : intersection)
System.out.println(integer);
From the Public Object blog:
“Unlike the traditional approach, these methods don’t do any copies! Instead, they return views that delegate to the provided sets. In the occasional case when the copy is worthwhile, there’s a handy method immutableCopy to give you one.”
Similarly, for maps, we have:
MapDifference differenceMap = Maps.difference(mapA, mapB);
and with that MapDifference, we can do stuff like:
differenceMap.areEqual(); Map entriesDiffering = differenceMap.entriesDiffering(); Map entriesOnlyOnLeft = differenceMap.entriesOnlyOnLeft(); Map entriesOnlyOnRight = differenceMap.entriesOnlyOnRight(); Map entriesInCommon = differenceMap.entriesInCommon();
Thank you, Google Collections
Validation with Preconditions
Bent André, a colleague and newest addition to the Codemunchies clan, introduced me to this concept earlier this summer, but it wasn’t until recently that I discovered that Google Collections actually included some of this stuff (we had our own implementation of a similar concept).
So, what is this concept? Well, validation is definitely something we do a lot, and it usually looks like something along these lines:
if (count <= 0) {
throw new IllegalArgumentException("must be positive: " + count);
}
We want to validate that the calling method invoked our method with the correct arguments. And if wrong, the caller should be warned that he made en error.
As the Java doc explains:
“Precondition exceptions are used to signal that the calling method has made an error. This tells the caller that it should not have invoked the method when it did, with the arguments it did, or perhaps ever. Postcondition or other invariant failures should not throw these types of exceptions.”
So, with the Preconditions class (and static imports), we can replace the code above with the following simple line of code:
checkArgument(count > 0, "must be positive: %s", count);
Likewise, you have similar methods to check state or null values.
checkNotNull(entry);
Quite neat, don’t you think?
“Note that the sense of the expression is inverted; with Preconditions you declare what you expect to be true, just as you do with an assert or a JUnit assertTrue call.”
From the excellent blog series on Google Collections over at Public Object:
“Preconditions provides methods for state validation. It makes input validation compact enough that you’ll always want to do it! And unlike Java’s built-in assert, Preconditions is always enabled.”
A great example of what I find all over the place in my code at Integrasco is the following:
public PostExample(final String title, final Date date, final String author) {
//some code to validate that title is not null
//some code to validate that date is not null
//some code to validate that author is not null
this.title = title;
this.date = date;
this.author = author;
}
Now look at how smooth your code becomes with Preconditions:
public PostExample(final String title, final Date date, final String author) {
this.title = checkNotNull(title);
this.date = checkNotNull(date);
this.author = checkNotNull(author);
}
Is that neat or what?
We will publish a post on this in more detail soon with regards to exceptions and validations, so stay tuned!
One collection to rule them all! – The Multimap
I can’t even count how many times I’ve made a Map where each key can have multiple values and ended up with the Map<K, List<V>> structure.
And the hassle of adding things to such structures go along the lines of:
Map<Person, List<BlogPost>> map = new HashMap<Person, List<BlogPost>>();
public void addBlogPost(final Person author, final BlogPost blogPost) {
List<BlogPost> blogPosts = map.get(author);
if (blogPosts == null) {
blogPosts = new ArrayList<BlogPost>();
map.put(author, blogPosts);
}
blogPosts.add(blogPost);
}
Don’t tell me you haven’t ever done this? With the Multimap collection from Google Collections, we can do this in the following (very sweet if I may say so) fashion:
Multimap<Person, BlogPost> multimap = ArrayListMultimap.create();
public void addBlogPost(final Person author, final BlogPost blogPost) {
multimap.put(author, blogPost)
}
Whoop, whoop!
Google Collections provides several implementations of Multimaps, for instance HashMultimap if you want to prevent duplicate pairs, TreeMultimap if you need the pairs in natural order, or LinkedHashMultimap if you need the ability to iterate the maps in insertion-order.
Multimaps provides several utility methods as well, go check out the API documentation on Multimap and Multimaps!
Excited yet? Keep reading!
Partitioning collections
I called this section Partitioning, and I guess you could say it is exactly what we covered under “Filtering Collections” in the previous blog post of this series, but when we apply these concepts in combination with functions and the Multimap, I think you will realize how powerful it can all be!
Let us pretend that we have a list of Maps. Each Map represent a document with certain attributes. A map may look something like this:
mapOf("type", "blog", "id", "292", "author", "john");
I.e., we have three keys, namely “type”, “id”, and “author”.
So our list of maps have the following structure:
List<Map<String, String>> listOfMaps
Now, we want to partition our list into several lists, by the type of entry. Let’s say that one type can be “blog”, another could be “news”, etc.
Now without Google Collections, that would be a real pain in the ass! We would have to loop the list, check the key of each map, then organize them into individual lists. And the hassle would be even bigger if we don’t know what types that we have! Following me?
With a little bit of Function magic, and the use of Multimaps, we can do this in a fairly elegant way:
Multimap<String, Map<String, String>> partitionedMap = Multimaps.index(
listOfMaps,
new Function<Map<String, String>, String>() {
public String apply(final Map<String, String> from) {
return from.get("type");
}
});
Now we have a Multimap where each key represents the type!
If we want all the maps for a specific type, all we need to do is ask our multimap for it!
Okay, that’s it for now! Hope you enjoyed the ride and that maybe you got inspired to check out these really great projects from the developers over at Google! Feedback is highly appreciated!


Thanks again for this great series!
A few things..
One, for 1.0-final I’ve added to the SetView javadoc this:
“There is usually no reason to retain a reference of type SetView; typically, you either use it as a plain Set, or immediately invoke immutableCopy() or copyInto(S) and forget the SetView itself.”
We really never intended to see “SetView union = …” in user code; it’s meant to be just a means to an end.
Not that it is _harmful_. You’re safe to use it.
The only issue with “Similarly, MapDifference…” is that MapDifference is a little bit different: it’s NOT a view. It does not update as the backing maps do. It copies data at the time Maps.difference() is invoked.
Re: Preconditions, be warned that ONLY %s is supported, not any of the other String.format() specifiers. (Sorry.)
Nothing incorrect in here though, of course! Thanks again!
Thanks Kevin! And thanks for all the effort you guys have put into these wonderful life-savers for us average-joes;)
Thanks for pointing out the specifics of MapDifference and the changes you’ve made to SetView:) I’ll be sure to check that out! With regards to string specifiers thats clearly stated in the JavaDoc, but I forgot to mention that in the blog post. Stay tuned for our article on Exceptions and validation (soon) where we explain the approach we have been using for this.
Cheers!
- Aleks
i dont see mapOf method in goog-collectns….is it your own method
@fdse: Hi! Yes, Its my own, but it’s just a wrapper for the Google Collection ImmutableMap.of() method. Simply because there is also an ImmutableList.of() method, and I like static imports – there will be a problem:)