Thursday, April 7, 2011

Lambdas in Java: constructor references

One thing I'm extremely excited about is the addition of support for lambda expressions in JDK 8. I've been following the Project Lambda mailing list since its creation and watching as things have evolved (and as it slipped from JDK 7, sadly... though there really wasn't time for it). Anyway, since I'm constantly thinking "Gahhh! If only Java had lambdas already!" when I'm working, I thought I should do some posts talking about what I'm looking forward to. Most of them will probably involve Guava (since it's one of my favorite things in Java) and how things you can do currently with it will be easier and read nicer using lambdas.

Today, I want to talk about constructor references! Basic support for them was added to the lambda repository of OpenJDK back in January.

A constructor reference is, as its name implies, a reference to a class constructor. Creating such a reference gives you an object implementing some interface and having a single method that, when called, will call the constructor and return the new instance that is created. For a simple example of how constructor references can help make code that's currently verbose nice and simple, consider the following code:

This code creates a Multimap sorted by keys but with unsorted ArrayLists holding values. One thing stands out here: the Supplier. That's a lot of code just to say "I want to make an ArrayList for each collection". But there isn't really any better way to do that in Java. Now take a look at how a constructor reference improves this:

The whole bulky Supplier from the first example has been replaced with ArrayList<String>#new. Just that! The reference to the no-arg constructor for ArrayList will be translated to a Supplier<ArrayList<String>> since it has a compatible method signature (no arguments and returns an ArrayList<String>). This is a huge improvement! Not only does it cut out 2/3 of the lines of code here (and a lot of ugly indenting, etc.), it's much clearer what we're doing.

What if you want to specify the initial capacity for the lists that are created? This is just as easy: use ArrayList<String>#new(100) instead. This will call the constructor that takes an int argument each time, passing the value 100.

Of course, even without constructor references all this would be relatively easy using lambda expressions: ArrayList<String>#new would instead be something like:

#{ -> new ArrayList<String>() }

It's nice to see constructors are getting the same treatment methods are, though.

As a side note, boy do I ever wish that I could use markdown on this blog. If writing a nicely formatted blog post were as easy as writing a StackOverflow answer... well, maybe I'd do it a little more often!

0 comments:

Post a Comment