Elvis carried away by spaceships

I love teaching Groovy to existing Java developers, because they have such a hard time holding back Tears Of Joy when they see how much easier life can be. Today, though, I did a quick demo that resulted in a line of Groovy that was so amusing I had to post it here.

Consider a trivial POGO (Plain Old Groovy Object) called Course:

class Course
    String name
    int days
    String toString() { "($name,$days)" }

The goal was to take a collection of courses and sort it by the number of days. That’s really easy in Groovy:

def courses = [
    new Course(name:'Groovy',days:4),
    new Course(name:'Grails',days:3),
    new Course(name:'Spring',days:4),
    new Course(name:'Hibernate',days:3)

assert courses.toString() == '[(Groovy,4), (Grails,3), (Spring,4), (Hibernate,3)]'

courses.sort { it.days }

assert courses*.days == [3, 3, 4, 4]

The sort method in the java.util.Collection class is part of the Groovy JDK, meaning it’s one of the methods Groovy adds to the standard Java libraries. It takes a closure of either one or two arguments. In this case, I’m using the one-argument closure, which is used to select a property on which to base the sort. By specifying it.days in the closure, I’m telling the sort method to sort the courses based on their days property. Then I verify that the sort worked by checking that the courses are the right order, using the spread-dot operator to just look at the number of days.

In class the question that always comes up is, can I sort by days and then by name? In other words, if two courses have the same number of days, can I then sort by the name property?

That’s what the two-argument closure on the sort method is for. The two arguments are references to any pair of courses, and the closure should return a negative number, zero, or positive number according to whether the first course is less than, equal to, or greater than the second.

Here’s where things get amusing. The sort I want is:

courses.sort { a,b ->
    a.days <=> b.days ?: a.name <=> b.name

assert courses.toString() == '[(Grails,3), (Hibernate,3), (Groovy,4), (Spring,4)]'

The body of the closure on sort uses the spaceship operator <=>, which returns -1, 0, or 1 depending on whether the left side is less than, equal to, or greater than the right side. I use spaceship to compare the days properties. Then I add the Elvis operator ?: which means if the days comparison is not zero, use it, but otherwise use the following comparison, which uses another spaceship to compare by name.

It’s only after writing the code in class that one of the students pointed out that I had Elvis in between two spaceships, leading to the following observations:

  1. The spaceships are there to return Elvis to his home planet
  2. It takes two spaceships, working in tandem, to carry Elvis away, in much the same way two swallows can carry a coconut in tandem
  3. Therefore, the Elvis being carried away must be the fat Elvis from the 70s, rather than the thin, cool Elvis from the 50s

Either way, after the sort is finished, Elvis has left the building.

Thank you, thank you very much.

About Ken Kousen
I am a Java Champion and the author of the books "Modern Java Recipes" (O'Reilly Media), "Gradle Recipes for Android" (O'Reilly Media), and "Making Java Groovy" (Manning), as well as over a dozen video courses at Safari Books Online. I'm a regular member of the No Fluff, Just Stuff conference tour and have given talks all over the world. Through my company, Kousen IT, Inc, I've taught training courses to and worked with thousands of developers.

2 Responses to Elvis carried away by spaceships

  1. Pingback: GroovyMag - the magazine for Groovy and Grails developers about Groovy programming and Grails development

  2. Pingback: can we use two criterias in sort | PHP Developer Resource

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: