Beautiful code with Google Collections, Guava and static imports

Original blog:

Original Author: Aleksander Stensby

So I’ve been advocating Google Collections to all my colleagues since early this summer. Kevin Bourrillion said that one of his colleagues had told him that “not being able to use the Google Collections was like ‘coding with one hand tied behind his back.’“.

I couldn’t agree more with Kevin’s colleague!

Maybe the title of this blog entry is a bit strange. I mean “beautiful code”. I guess I could have said “less verbose” Java code, but hey, that doesn’t have the same magic sound to it!

Before I start this whole highly promotional rant about my new favorite java libraries, let me ask you a couple of questions:
How many times have you written something like this in your code:

1.Map<String, Map<Long, List<String>>> map = new HashMap<String, Map<Long,List<String>>>();

Or maybe something along these lines:

1.int a = 5;
2.int b = 10;
3.int compareTo = Integer.valueOf(a).compareTo(Integer.valueOf(b));

(Or with lots of ifs and elses;))

And how many times have you written something along these lines, just to read something from a file?:

01.File file = new File(getClass().getResource("/test.txt").getFile());
02.BufferedReader reader;
03.String text = "";
04.try {
05.reader = new BufferedReader(new FileReader(file));
06.String line = null;
07.while (true) {
08.line = reader.readLine();
09.if (line == null) {
10.break;
11.}
12.text += line.trim() + "\n";
13.}
14.reader.close();
15.reader = null;
16.} catch (FileNotFoundException e1) {
17.e1.printStackTrace();
18.} catch (IOException e) {
19.e.printStackTrace();
20.}

Yeah, I thought so… So what’s all the fuzz about? We’ve had Apache Commons Collections for several years. Why should we use yet another collections library?
I’ve read several comments like this one:

“Any Java programmer who’s been around awhile will already have accumulated most of these types of utility classes.”

Well, yes, that might be (and should hopefully) be true for most developers. But then again, there’s so much more to it than just getting rid of boiler plate code and reusing nifty utils! In this blog post I want to show you some of the things that really made me curious about – then later addicted to – Google Collections.

Like Jared Levy once said:

The library’s functionality simplifies your code so it’s easier to write, read, and maintain. While you can survive without such features, the Google Collections Library will improve your productivity as a developer, while reducing the amount of boilerplate low-level code you need to write.

Cookies?http://www.flickr.com/photos/orcaman/ / CC BY 2.0

Furthermore I want to show you some of the cool stuff that the guys over at Google have been churning up under the name Guava, and how YOU as a Java developer can utilize these nifty libraries to make your code cleaner, faster to write, and once and for all get rid of all a lot of that boiler plate code we all hate so much!

Google Guava is the Google Core Libraries for Java 1.6. It is still a rather immature library that is subject to changes over the coming months, but will eventually be THE Java library;) Google Collections will become part of Guava once Collections reaches it’s 1.0 release. Guava (and Google Collections) have been pioneered by several Google developers and is widely used in their “myriad of Java projects”. Among others, the people behind it are Kevin Bourrillion, Jared Levy, Crazy Bob Lee, Josh Bloch(!) (Chief Java Architect at Google etc.) and limpbizkit (have no clue what this guy’s name is – anyone?:p). Google Collections has been around since 2007 (I think?) but Guava saw the light of day in September 2009.

In part one of this blog series I’ll give you an introduction to Google Collections and show you how you can benefit from using Guava with Collections to reduce the amount of boilerplate code in your projects (and gain access to the new and faster data structures that they provide!). In part 2 we will dive deeper into the more advanced features that Guava and Collections offers to you as a Java developer, so stay tuned!

Google Collections at a glance
Obviously one blog post will not give Google Collections the amount of in-depth coverage it deserves, so I’ve decided to just spend some time with the basic yet powerful features that I use on a daily basis when I write code.
First of all, don’t do this:

1.Map<String, Map<Long, List<String>>> map = new HashMap<String, Map<Long,List<String>>>();

Do this:

1.Map<String, Map<Long, List<String>>> map = Maps.newHashMap();

or rather this, (with static imports):

1.Map<String, Map<Long, List<String>>>map = newHashMap();

Nice, right? Thanks to generics and those handy factory methods that the Collections guys have provided us with, we no longer have to write things that Java really should understand, right? Yeah, I know this will be part of JDK 7, and that’s great. But Google Collections is here, now!

Similar to the static utility methods that com.google.common.collect.Maps provide, we also have Lists and Sets.

1.Lists.newArrayList();
2.Sets.newHashSet();

…and more! Go check it out for yourself!

Populating lists and maps
When writing unit tests you often want to populate lists (or maps, or sets) with dummy data, and as the sloppy “duct-tape” programmer that I am, I’ve found the same code over and over again in my tests, along these lines:

1.List<String> list = new ArrayList<String>();
2.list.add("a");
3.list.add("b");
4.list.add("c");
5.list.add("d");

Yeah, I know. Dirty. I want an immutable list, populated with my dummy data, and I want to do it with one line of code! How? Well, that’s easy!

1.ImmutableList<String> of = ImmutableList.of("a", "b", "c", "d");

Same goes for Maps!

1.ImmutableMap<String,String> map = ImmutableMap.of("key1", "value1", "key2", "value2");

I’ve grown really fond of these simple, yet powerful ways of writing code now. I wanted to write that line in an even shorter way, but couldn’t do it out of the box with static imports since both ImmutableList and ImmutableMap had the method “of”. But a quick workaround was simply to wrap these creational factory methods (and builder methods that they provide) in a collection util of our own. So for immutable maps and lists I simply write:

1.ImmutableMap<String,String> map2 = mapOf("key1", "value1", "key2", "value2")

or

1.ImmutableList<String> list2 = listOf("a", "b", "c", "d");

And if I want to populate an ArrayList (or a HashMap) I use:

1.ArrayList<String> list3 = arrayListOf("a", "b", "c", "d");

The choice is yours, obviously, but you have to admit, it’s quite neat compared to the “old” way, right?
Apart from the handy and clean ways of creating collections and populating them, we are also provided with lots of additional utility methods like filtering, set intersections and union, ordering and even some neat functional stuff! I’ll cover that in part 2!

Static imports and Eclipse templates
Before I wrap this up I want to tell you about how I use Collections even more efficiently when I code by using the Eclipse Code templates. (I assume you have similar features in IDEA and other IDE’s, so you can probably follow this recipe to some extent anyways):

Being a user of Eclipse I love shortcuts (check out Jaran’s post about MouseFeed and how you can easily learn Eclipse shortcuts).
Okay, Ctrl+Space is your friend! It’s also known as auto-complete:)
With Eclipse, you can create a template that binds to an auto-complete key-word and this is where the magic begins!
Instead of having to write Maps.newHashMap() or (even better – adding the method as a static import and writing newHashMap()) i simply type “newH”, hit ctrl+space and MAGIC! ;)

Go to Window – Preferences in Eclipse. Go to Java -> Editor -> Templates and hit “New”.
The Name will be your shortcut, I usually name mine the method, i.e. “newHashMap” in this case.
Add your description if you like, for instance “Import static Maps.newHashMap”
And add the following Pattern:
${:importStatic(com.google.common.collect.Maps.newHashMap)}newHashMap();${cursor}
And that’s all there is to it! Now go crazy and add templates for all those method that you use alot!

Guava at a (very quick) glance
Last but not least, let me show you how you can use Guava to deal with the two remaining question I opened this blog post with:
Read lines from a file:

1.File file = new File(getClass().getResource("/test.txt").getFile());
2.List<String> lines = null;
3.try {
4.lines = Files.readLines(file, Charsets.UTF_8);
5.} catch (IOException e) {
6.e.printStackTrace();
7.}

Compare two primitives?

1.int compare = Ints.compare(a, b);

Convert a list of Integers to an array of primitive ints?

1.List<Integer> list = listOf(1, 2, 3, 4);
2.int[] array2 = Ints.toArray(list);

Guava provides us with a comprehensive extension to the Core Java Libraries. Among other things we gain access to utilities for working with primitives through the Ints, Doubles, Floats, Shorts, Bytes and Bools classes in the com.google.common.primitives package. The com.google.common.io package provides utilities for working with streams, buffers, files etc, and the concurrent package provides classes like Futures, Callables and Executors to ease the pain of writing concurrent code. In addition to all of this, Guava also provides us with some additions to Collections and a really neat CharMatcher class, Joiner and Splitter classes that I will cover next time!

Check out the source code here:
svn checkout http://guava-libraries.googlecode.com/svn/trunk/guava-libraries-read-only

Next time we’ll take a deeper dive into Guava and also some of the more advanced stuff in Google Collections like how we can make Java just a tiny bit more “functional”, the über collection “Multimap” and how we can use mapping functions to transform collections. Stay tuned, and please share your comments on this with us! Have you tried Guava or Google Collections? What are your thoughts?

Courtesy:

Original blog:

Original Author: Aleksander Stensby