5 Reasons to use Guava


Fri 21 October 2011

Guava is an open source library containing many classes for Java and written by Google. It's a potentially useful source of miscellaneous utility functions and classes that I'm sure many developers have written themselves before, or maybe just wanted and never had time to write. Here's 5 good reasons to use it!

1. Collection Initializers and Utilities

Generic homogeneous collections are a great feature to have in Java, but sometimes their construction is a bit too verbose, for example:

        
        final Map<String, Map<String, Integer>> lookup = new HashMap<String, Map<String, Integer>>();
        

Java 7 solves this problem in a really generic way, by allowing a limited form of type inference informally referred to as the Diamond Operator. So we can rewrite the above example as:

        final Map<String, Map<String, Integer>> lookup = new HashMap<>();
        
        

It's actually already possible to have this kind of inference for non-constructor methods in earlier Java releases, and Guava provides many ready made constructors for existing Java Collections. The above example can be written as:

        final Map<String, Map<String, Integer>> lookup = Maps.newHashMap();
        

Guava also provides many useful utility functions for collections under the Maps, Sets et al. classes. Particular favourites of mine are the Sets.union and Sets.intersection methods that return views on the sets, rather than recomputing the values.

2. Limited Functional-Style Programming

Guava provides some common methods for passing around methods in a functional style. For example, the map function that many functional programming languages have exists in the form of the Collections2.transform method. Collections2 also has a filter method that allows you to restrict what values are in a collection. For example to remove the elements from a collection that are null, and store it in another collection, you can do the following:

        Collection<?> noNullsCollection = filter(someCollection, notNull());
        

Its important to remember that in both cases the function returns a new collection, rather than modifying the existing one and that the resulting collections are lazily computed.

3. Multimaps and Bimaps

A really common usage case for a Map involves storing multiple values for a single key. Using the standard Java Collections that's usually accomplished by using another collection as the value type. This unfortunately ends up involving a lot of ceremony that needs to be repeated in terms of initializing the collection. Multimaps clear this up quite a bit, for example:

        Multimap<String, Integer> scores = HashMultimap.create();
        scores.put("Bob", 20);
        scores.put("Bob", 10);
        scores.put("Bob", 15);
        System.out.println(Collections.max(scores.get("Bob"))); // prints 20
        

There's also a BiMap class which goes in the other direction - that is to say that it enforces uniqueness of values as well as keys. Since values are also unique, a BiMap can be used in reverse.

4. Easy Hashcodes and Comparators

Its pretty common to want to generate a hashcode for a class in Java from the hashcodes of its fields. Guava provides a utility method for this in the Objects class, here's an example:

        int foo;
        String bar;
        
        @Override
        public int hashCode() {
        	return Objects.hashCode(foo, bar);
        }
        

Don't forget to maintain the equals contract if you're defining a hashcode method.

Comparators are another example where writing them frequently involves chaining together a sequence of operations. Guava provides a ComparisonChain class in order to ease this process. Here's an example with an int and String class:

        int foo;
        String bar;
        
        @Override
        public int compareTo(final GuavaExample o) {
        	return ComparisonChain.start().compare(foo, o.foo).compare(bar, o.bar).result();
        }
        

5. Defensive Coding

Do you ever find yourself writing certain preconditions for your methods regularly? Sometimes these can be unnecessarily verbose, or fail to convey intent as directly. Guava provides the Preconditions class with a series of common preconditions.

For example instead of an if statement and explicit exception throw ...

        if (count <= 0) {
            throw new IllegalArgumentException("must be positive: " + count);
        }
        

... you can use an explicit precondition:

        checkArgument(count > 0, "must be positive: %s", count);
        

Conclusions

Being able to replace existing library classes with those from guava, helps you to reduce the amount of code you need to maintain and offers a potential productivity boost. There are alternatives for example the Apache Commons project. It might be the case that you already use and know of these libraries, or prefer their approach and api to the Guava approach. Guava does have an Idea Graveyard - which gives you some idea of what the Google engineers perceive to be the limits of the library, or a bad design decision. You may not individually agree with these choices, at which point you're back to writing your own library classes. Overall though Guava encourages a terser and less ceremonious style and some appropriate application of Guava could help many Java projects.

If you've enjoyed this blog, why not read our previous blog post on Guava's EventBus.

This article has been translated into korean.