The Groovy Spaceship Operator Explained

A brief explanation of the Groovy spaceship operator, its usage, and the advantages of using it..

Object Partners

While extending an existing Grails application bits of research around sorting lists using Groovy ensued. My first stop was Groovy In Action wherein the operator <=> was shown in a closure used for sorting, but with no explanation. Under Operators in the index, it became known that <=> is “The Spaceship Operator” - no doubt due to its similarity in look to a flying saucer. Sadly the referenced section of text also offered little in explaining what this bugger did exactly.

The spaceship operator has it’s roots in Perl and has found it’s way in to languages like Groovy and Ruby. The spaceship is a relational operator that performs like Java’s compareTo() comparing two objects and returning -1, 0, or +1 depending on the value of the left argument as compared to the right. If the left argument is greater than the right, the operator returns 1. If the left argument is less than the right, the operator returns −1. If the arguments are equal, 0 is returned. When using Groovy/Grails, if the arguments are not of comparable types, a ClassCastException is thrown.

While the spaceship could be used wherever you would use compareTo(), it seems most references to it are found in sorting. For example the following two lines would have identical results:

_things.sort{ Thing a, Thing b -> b.beginDate <=> a.beginDate }

things.sort{ Thing a, Thing b -> b.beginDate.compareTo( a.beginDate ) }_

Other examples of its behaviour from the Groovy Console:

groovy> def d = new Date() groovy> println d <=> d groovy> println 3 <=> 4 groovy> println “doberman” <=> “dachshund” groovy> println d <=> new Date()

0 -1 1 -1

Perhaps the greatest advantage of using the Groovy comparison operators is the graceful handling of nulls such that x <=> y will never throw a NullPointerException:

groovy> println “dachshund” <=> null groovy> println null <=> “dachshund” groovy> println null <=> null

1 -1 0

In addition when comparing numbers of different types the type coercion rules apply to convert numbers to the largest numeric type before the comparison. So the following is valid in Groovy1:

groovy> Byte a = 27 groovy> Double b = 9 groovy> println a instanceof Byte groovy> println b instanceof Double groovy> println a > b

true true true

We come in peace - happy comparisons! For more on Groovy operator overloading look here.

1 “Groovy - Operator Overloading” Available at: http://groovy.codehaus.org/Operator+Overloading 26 January 2010

Share this Post

Related Blog Posts

JVM

Immutable Data Structures in Concurrent Java Applications

February 1st, 2010

Using immutable data structures to minimize complexity and risk in concurrent applications.

Object Partners
JVM

Using JPA and JAXB Annotations in the Same Object

January 25th, 2010

Using both JPA and JAXB annotations on the same member of an object can cause runtime errors if not done correctly. Heres how to do it.

Steve McCoole
JVM

Subversion and Hudson From Scratch

January 18th, 2010

A step-by-step approach to get Hudson Continuous Integration working behind an Apache web server, building an Ant project fetched from Subversion.

Object Partners

About the author