Groovy collection comparison is easy

One thing I found myself doing more than I wanted with java was collection comparison. Many times, you might have a large list of all available items, and a smaller list of selected items. Commonly, you might want to find all the items that exist in the large collection, but have not been ’selected’ in the smaller collection. Invariably in java, this means nested loops.

Not so much with groovy.

List subtraction
def smallList = [1,3,5]
def bigList = [1,1,1,2,3,4,4,4,5,6,7,7,8,9]

def result = bigList - smallList
println result.class
println result

The result is:

class java.util.ArrayList
[2, 4, 4, 4, 6, 7, 7, 8, 9]

Groovy correctly made the assumption that I was making a List in my snippet above. And it removed any element within the first list where equals() was true for an element in the first list. That means it took away three 1’s and one 3. Keep in mind the original collections are untouched.

But what if I want to compare a List and a Set?

Set/List addition
Set mySet = [1,3,5]

List myList = [0,1,2,3,4,0,1,2,3,4,5,6,7,8,9]

def addition = myList + mySet
println addition.class
println addition

addition = mySet + myList
println addition.class
println addition

Now we’re adding a List and a Set together, and the result is different depending on which is the first operand:

class java.util.ArrayList
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 3, 5]
class java.util.HashSet
[2, 4, 9, 8, 6, 1, 3, 7, 5, 0]

If the List is the first operand, groovy assumes you want to treat the following operand as a List as well, and it just tacks the values onto the end. But when the Set is first, groovy first converts the second argument into a Set as well before doing its addition. This removes all but unique elements from it before performing the addition.

Set/List subtraction
Set mySet = [1,3,5]

List myList = [0,1,2,3,4,0,1,2,3,4,5,6,7,8,9]

def subtraction = myList - mySet
println subtraction.class
println subtraction

subtraction = mySet - myList
println subtraction.class
println subtraction

We should again see the automatic type conversion as in the above examples depending on which type is the first operand. In the results below, you can see that all elements within the set were removed from the list (there are no 1’s, 3’s, or 5’s). The second subtraction results in 0 elements, because the List (which is converted to a Set) being subtracted contains 1, 3, and 5, so all are removed from the original Set.

class java.util.ArrayList
[0, 2, 4, 0, 2, 4, 6, 7, 8, 9]
class java.util.HashSet
[]

Good stuff. This is just another example of how groovy does away with a lot of the annoying things you have to do with java.

When groovy comes across an operator like “-” or “+”, it looks for a method on the left operand called either “plus” or “minus”. So in the above examples, mySet - myList is the same as mySet.minus(myList).

6 Responses to “Groovy collection comparison is easy”

  1. Robert O'Connor Says:

    Nice.

  2. Dan Lewis Says:

    If only there was a way to subtract a collection from another using plain old Java. :P

  3. Matthew Taylor Says:

    In all fairness, yes, you can do similar things with the Apache collections package. But why would you want to go looking for tons of third party jars to add to your project when all you really need is groovy-all.jar, baby.

    Also, I’d like to see you try to use the ‘+’ and ‘-’ on collections using any third party java jar.

  4. ahmetaa Says:

    Just write a simple helper. I guarantee that it will be 20 times faster than Groovy.

  5. Matthew Taylor Says:

    Unless you are doing some math in your app (and in all my J2EE experience, you hardly ever have much of that), the most time-consuming part of a J2EE application is communicating with another service. Whether it is calling a web service or a round-trip to the database, that is where your time costs comes into play.

    Groovy is slow with math, but that is such a small part of today’s applications (it is all abstracted to much lower levels). I think you would be surprised by how little you would notice the speed difference between groovy and java in a case like this.

    You might write a helper that takes you 6 hours to write (if you test it properly, possibly more), but you could have written your code in 10 seconds if you were using groovy, and you would have 100% confidence that it would work properly the first time.

    Developer velocity is more important than program velocity.
  6. Jim LoVerde Says:

    Regarding performance, I wrote a simple helper. Java was about 6 times faster, quite a bit less than 20 times faster. And that’s not bad when you consider that quite a few Groovy performance improvements are in the pipeline.

    http://jimloverde.blogspot.com/2008/04/simple-java-vs-groovy-perfomance.html

Leave a Reply