It turns out that it’s easy to turn a Java enum into a type that can be used in a Groovy range.

Consider a simple enum representing the seasons:


public enum Season {
    WINTER, SPRING, SUMMER FALL
}

Since enums implement the Comparable interface, they have a compareTo() method. Despite that, however, you can’t use an enum with < or > in Java.


// Won't compile in Java
// if (Season.WINTER > Season.FALL) { ... }

In Groovy, though, any class that implements Comparable can be used with < and >:


// Groovy version
assert Season.FALL > Season.WINTER

That works just fine.

Since the enum already implements Comparable, turning it into a Groovy range simply requires adding in a next() and a previous() method. Here’s one way to do that, relying on the ordinal() method in enum, which returns the index of the enum in the overall collection.


public enum Season {
    WINTER, SPRING, SUMMER, FALL;

    Season next() {
        Season[] vals = Season.values();
        return vals[(this.ordinal() + 1) % vals.length];
    }

    Season previous() {
        Season[] vals = Season.values();
        return vals[(this.ordinal() - 1 + vals.length) % vals.length];
    }
}

Now in Groovy you can write:


(Season.WINTER..Season.FALL).each {
    println it
}

or even


for (s in Season.values()) {
    println (s++)
}

for (s in Season.values()) {
    println (s--)
}

To be honest, I’m not sure where I’m ever going to use that capability, but it’s interesting.

(In Java, the EnumSet.range() method returns a collection that can be used in the Java 5 for-each loop:

for (Season s : EnumSet.range(Season.WINTER, Season.FALL) { ... }

but you still can’t use the < or > operators. And the Groovy approach is still simpler.)

4 thoughts on “Turning Java enums into Groovy ranges

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.