Sorting By Functions in Groovy

Sometimes we’ll want to sort a collection by something other than its natural order. For example, suppose we wanted to sort strings by their length instead of alphabetically. Here’s an example of custom sorts in Groovy.

import groovy.transform.Canonical

// We implement a comparison function for string lengths.
def lenCmp = { a, b -> a.length() <=> b.length() }

def fruits = ["peach", "banana", "kiwi"]

// Now we can call sort() with this custom comparison function to sort fruits by name length.
fruits.sort(lenCmp)
println fruits

// We can use the same technique to sort a list of values that aren't built-in types.
@Canonical
class Person {
    String name
    int age
}

def people = [
    new Person(name: "Jax", age: 37),
    new Person(name: "TJ", age: 25),
    new Person(name: "Alex", age: 72)
]

// Sort people by age using sort() with a custom comparator.
people.sort { a, b -> a.age <=> b.age }
println people

In this Groovy example, we’re using the <=> (spaceship) operator for comparisons, which is equivalent to the cmp.Compare function in Go. The sort() method in Groovy can take a closure as an argument, which acts as the comparison function.

We define a Person class using the @Canonical annotation, which automatically generates toString, equals, and hashCode methods for us.

Note that in Groovy, we don’t need to explicitly declare the type of variables or method return types, as it’s a dynamically typed language.

To run the program, save it as sorting_by_functions.groovy and use the groovy command:

$ groovy sorting_by_functions.groovy
[kiwi, peach, banana]
[Person(TJ, 25), Person(Jax, 37), Person(Alex, 72)]

This example demonstrates how to perform custom sorting in Groovy, both for built-in types like strings and for custom classes. The sort() method in Groovy is very flexible and can accept custom comparison logic, making it easy to sort collections based on any criteria you need.