Guava

A public service announcement for Java programmers.

Google has released as Free software a bunch of convenience libraries used internally in Google Java code. The project is (very cleverly) called Guava.

The libraries span a huge range of functionality, but I think that in general they help to promote a more functional programming style and they paper over some of Java's warts.

Here are three of my favorite things from Guava, but if you read the Javadocs you will undoubtedly find more cool stuff. Looking at all of this, you might decide that it's all simple stuff that you could implement yourself in about five minutes. Of course you could (in some cases, anyway), but why would you?

Immutable collections

Create an immutable list (as you might recall, every Java array is mutable, which can be a huge source of pain):

List<String> answers = ImmutableList.of("yes", "no", "maybe");

There's also a Builder pattern for more complex constructions, and analogous classes Immutable{Map,Multimap,Set,SortedMap,SortedSet}.

Collection factory methods

Here's some standard Java code to instantiate a collection:

List<Foo> foos = new ArrayList<Foo>()

Using the Lists class, you can rewrite that as the following:

List<Foo> foos = Lists.newArrayList()

Usually factory methods are a way for you to give the callee the flexibility of returning different classes at runtime. That's not the case here— Lists.newArrayList will always return an ArrayList (unsurprisingly). But Java does type inference for a call of this type, so you save the hassle of having to repeat yourself by writing the generic type Foo on both sides of the assignment, every time you create a new collection.

There are analogous classes Maps and Sets, which also contain other useful utilities in addition to these factory methods.

Splitter

Some simple illustrative examples for splitting a string using Guava's Splitter class:

Splitter.on(",").split("foo,bar,baz");
// ==> an iterable containing "foo", "bar", "baz"

Splitter.on(",")
    .trimResults()
    .omitEmptyStrings()
    .split("foo,bar , baz,,,");
// ==> an iterable containing "foo", "bar", "baz"

But wait, doesn't Java already do string splitting? Yes! Yes, it does. And this is how (emphasis mine):

String.split

public String[] split(String regex, int limit)

Splits this string around matches of the given regular expression.

The array returned by this method contains each substring of this string that is terminated by another substring that matches the given expression or is terminated by the end of the string. The substrings in the array are in the order in which they occur in this string. If the expression does not match any part of the input then the resulting array has just one element, namely this string.

The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.

This is a bizarre and unmemorable edge case in the API. I guarantee that upon finishing this paragraph, you will promptly forget about it until about two hours into debugging a failure caused by it. You can save yourself some grief if you just use Splitter. Stay away from String.split.

No comments:

Post a Comment