Using collect on Groovy collections
Saturday, March 29th, 2008When you find something you like, you want to share it with the world. Here are some more tricks when working with collections in Groovy that makes programming fun again! ;)
Let’s get a sample model and some data first, then we’ll get to the fun and easy Grooviness…
class RockStar {
def name
def bands
def numberOfGroupies
}
def mike = new RockStar(name:"Mike Patton",
bands:["Faith No More","Mr. Bungle"],
numberOfGroupies:2214)
def bono = new RockStar(name:"Bono",
bands:["U2"],
numberOfGroupies:543582)
def slash = new RockStar(name:"Saul Hudson",
bands:["Guns N Roses", "Velvet Revolver"],
numberOfGroupies:32544)
def scott = new RockStar(name:"Scott Weiland",
bands:["Stone Temple Pilots", "Velvet Revolver"],
numberOfGroupies:41880)
def rockStarList = [mike, bono, slash, scott]
As you can see, I have created a simple POGO class, loaded some beans, then tossed them into a simple list.
Now what? Well, maybe we need to make a list of all the bands our rock stars are a part of, or better yet, a set. We don’t want the same band listed twice now! So what is the easiest way to make this happen? Let me introduce you to a very useful method in your Groovy toolbox, collect.
Set allBands = rockStarList.collect { rockStar ->
rockStar.bands
}
The closure you pass to the collect method is used to transform that list item into whatever you want. In this case, I’m taking a list of RockStars and transforming it into a set of string lists, containing band names. When you run this, you will get a Set that contains the Lists within the objects. This is really useful when you have a list of domain classes that you don’t really need, but you need to get at some information inside each of them.
But this is still no good! We want a List of Strings that contain band names, not a List of Lists! But wait! Groovy makes this dead-easy to fix:
Set allBands = rockStarList.collect { rockStar ->
rockStar.bands
}.flatten()
Using the flatten list method does exactly what we want. It takes all the collections within the top-level collection and adds them recursively to the top-level collection, effectively flattening them all out into one collection.
Perfect. But you want to know the total number of groupies for every rock star? No problem.
def totalGroupies = rockStarList.collect {
it.numberOfGroupies
}.sum()
Before we call the sum() method, our closure returns a List containing Integer objects. If you call sum() on a list of any objects, this effectively calls the “plus()” method on each of the objects. Because the list is loaded with Integer objects, these all add up nicely.
And there you go:
There will be 620,220 groupies at the show.

