In part one and two of this blog series I gave an introduction to the excellent Google Collections and Guava libraries. In this blog post we will look at how you can use Google Collections to do filtering and ordering! Furthermore, I will show you how we can make Java just a tiny bit more “functional” with Google Collections!
Functions, Functions, Functions!!
Google Collections provides us with a couple of very neat things called Functions and Predicates! Similar to some of the magic you can do with for instance Scala, you can now do with good old non-functional Java! You’ll find these (and more) in the com.google.common.base package in Google Collections.
We will look at Predicates in the next section (on Filtering collections), but first let’s take a look at Functions!
Google Collections provides us with the interface Function<F, T>. In essence, a function is a transformation from one object to another.
The collection utility classes like Lists and Maps provide us with transformation methods:
topMap = Maps.transformValues(fromMap, function); toList = Lists.transform(fromList, function);
To exemplify, let’s say you have a Map of items and a corresponding price in Euros. So, you figure out that you want an easy way to convert all prices to Dollars. Traditionally we would have to loop through the map and update each value with the converted price. Tedious…
With functions, this becomes easy!
Map usdPriceMap = Maps.transformValues(eurPriceMap, new Function() {
double eurToUsd = 1.4888;
public Double apply(final Double from) {
return from * eurToUsd;
}
});
Well, you might say that the anonymous inner class makes this a bit messy, and this function would most likely be something that you want to reuse – still it demonstrates the functional aspect of things here. (C’mon please give us closures already!)
Similarly to the example above, we can also use Functions to transform from one object type to a completely different one – say for instance from an Integer to a String.
We will look further into Functions later in this blog series when I walk you through the Multimap collection and show how we can transform from one collection to a another with a little bit of function magic.
Filtering collections with predicates
One of the most common tasks I encounter when working with data at Integrasco is filtering and ordering large collections.
For the sake of simplicity, let’s say you have a list of names that you want to filter (in a rather stupid way):
List<String> names = listOf("Aleksander", "Jaran", "Integrasco", "Guava", "Java");
With com.google.common.collect.Iterables and com.google.common.base.Predicates we can filter our list for example to just contain Aleksander or Jaran:
Now I know that sounds pretty stupid, but you can also implement your own Predicates, for example to return names that have a length shorter than say 5 characters (I stole this example from Stephan over at codemonkeyism.com):
Iterable<String> filtered = filter(names, or(or(equalTo("Aleksander"),equalTo("Jaran")), lengthLessThan(5)));
Which will return us Aleksander, Jaran and Java (since Java is shorter than 5 chars.) The ‘or’ part here is a bit messy to read, but bear with me. The ‘equalTo’ and ‘or’ predicates are given to us for free by the Predicates class.
So to implement that lengthLessThan predicate, all you need to do is:
private static class LengthLessThanPredicate implements Predicate<String> {
private final int length;
private LengthLessThanPredicate(final int length) {
this.length = length;
}
public boolean apply(final String s) {
return s.length() < length;
}
}
Wrap that in whatever utility class you want and access it like this:
public static Predicate<String> lengthLessThan(final int length) {
return new LengthLessThanPredicate(length);
}
Check out Stephan’s blog post on writing fluent interfaces for Google Collections – It’s really quite neat!
Sorting / Ordering Collections
Thanks to the java Collections utility class we can do stuff like
Collections.sort(List<T>, Comparator<? super T>)
But sometimes we want to do more complex stuff, combining several Comparators and moreover we may want a view of the sorted list, without changing the original order.
Google Collections provides us with Ordering, which allow us greater control over our sorting.
Let’s say we have two simple comparators for a class Person, that compares by lastName or by firstName:
Comparator<Person> byLastName = new Comparator<Person>() {
public int compare(final Person p1, final Person p2) {
return p1.getLastName().compareTo(p2.getLastName());
}
};
Comparator<Person> byFirstName = new Comparator<Person>() {
public int compare(final Person p1, final Person p2) {
return p1.getFirstName().compareTo(p2.getFirstName());
}
};
Now, if we want to sort by last name first, then by first name, and then return the sorted results in reverse order, all we need to do is:
List<Person> sortedCopy = Ordering.from(byLastName).compound(byFirstName).reverse().sortedCopy(persons);
And even better, you don’t even need to create Comparators, you can just extend Ordering!
List<Person> sortedCopy = orderByLastName.compound(orderByFirstName).reverse().sortedCopy(persons);
Filtering and Sorting cont’d
So in part 1 on this blog series, Steve commented that in Scala, you can do stuff like the following:
people.filter(_.firstName == "Steve").sort(_.lastName < _.lastName)
i.e. get people named Steve from the list people, and then sort by their last name.
Syntactically, that line of Scala code is pretty neat! So let’s see what we can do with Google Collections then. Google Collections provides us with the Iterables class that we covered earlier in this blog post (under filtering). We can do both filter and transform with the Iterables class (and you can do the same with Collections2, provided by Google Collections as well).
So I wanted to have a crack at how to solve the same thing as Steve did with his line of Scala code, and even though it is not as neat, this is one way of solving the above Scala code with the use of Predicates and Ordering:
Ordering.from(byLastName).sortedCopy(filter(persons, withFirstName("Steve")));
Still not close to the syntactical sugar we get from Scala (and obviously we would need our “withFirstName” predicate and the “byLastName” Comparator), but at least this is much closer than where we were without Google Collections! (And it would become even easier to read if we take on Stephen’s approach to fluent interfaces).
As Kevin Bourrillion commented on another blog post on writing functional Java:
“The syntax sucks. At the same time, this stuff is now, has always been and will always be nothing but a stopgap measure until the right language change can come along, at which time we can finally really decide on the optimal syntax and have functional-style programming start actually making lives better in Java for once. So I’m undecided how much effort to put into the Function/Predicate stuff; it’s in the library more because it sort of had to be, not so much because we think it’s a crown jewel.”
In the next and final part of this blog series on Google Collections and Guava we will take a look at Set and Map operators in Google Collections, Validation with Preconditions and I will walk you through the wonderful Multimap collection and how we can use this for partitioning!
Stay tuned!



Even with Google collections it’s pretty bad and unreadable compared to say c#.
IList sortedPeople = people.Where(p => p.FirstName.Equals(“Steve”)).OrderBy(p => p.LastName).ToList();
And you find the c# line readable ??
Is there an equivalent to the “groupBy” closure from Groovy?
def listOfPersons = [[ name: 'Clark', city: 'London' ], [ name: 'Sharma', city: 'London' ], …]
def groupedPersons = listOfPersons.groupBy{ it.city }
println groupedPersons
->
[London:[[name:Clark, city:London], [name:Sharma, city:London]], SomeOtherTown: [.......]]
I really miss that feature in Java. Being able to transform a list of objects into a map by supplying a “grouping” function.
Hi Sakuraba! Yes there is actually! By combining Functions and the Multimap collection in Google Collections we can do just that! The next and final part of this blog series will cover just that! So stay tuned
@sboulay: I have to say that I agree with YeFFreY. That line of C# code is hardly what you can call readable.
Now, what if I tell you all that with a little bit of functional magic we can write the following fully valid line of java code:
filteredList = filter(persons, with("firstName", "aleksander"));
list = orderBy("lastName").sortedCopy(filter(persons, with("firstName", "aleksander")));
Iterable
We can even write the following:
List
Now that’s pretty cool – given the fact that it’s plain old Java…
Thanks for your answer, cant wait for your next blog post!
Does this mean one no longer needs LambdaJ when working with Google Collections?
I guess it’s a matter of taste. If you use closures alot it seems much more natural to do it the way that it is done in c#. The Scala example is pretty close. In fact, almost all programming languages do it this way (groovy, ruby, scala, fan, c#), java is really the odd one out here. I personally don’t like ‘with(“firstname”,”aleksander”)’ . Using strings by passes the benefits you get from the complier i.e making a spelling mistake.
here is an example that just got posted that uses google collections and tries to get around exactly what I pointed out. Notice that the person is trying to create property so you don’t have to use strings. Similarly, JPA 2.0 uses a meta model to get around this.
http://blog.javabien.net/2009/11/02/google-collections-and-enhanced-javabeans/
Love your posts, and the photography. I have been posting similar stuff on my blog, but more problem / solution focused, and to be honest have not done as good a job as you due to time constraints.
Have you looked at the Spring 3 release and SPeL? You can solve similar problems with that. It overlaps, and covers different areas. In fact if you look at what you can do with SPeL, Hamcrest and Guava the combined extra power is fantastic.
With SPeL you miss out on this ability to form an iterable backed by the original collection, but in some cases it can still be of use. I think your example from above would look a bit like this. Excuse any mistakes I am free coding this!
Iterable filtered = filter(names, or(or(equalTo(“Aleksander”),equalTo(“Jaran”)), lengthLessThan(5)));
List filtered = (List) parser.parseExpression(“#names.?[(Name == 'Aleksander' || Name == 'Jaran') && Name < 5 ]").getValue(names);
Not as pretty by any means, but interesting all the same.
See for detail:
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch07s02.html