Groovy Maps: Reverse Sort

15 / Apr / 2009 by Aman Aggarwal 6 comments

I want to quickly share how you can sort a Map by its key/value/field of valueObject; in either ascending or descending order using Groovy

I created a Map<String, Person> as follows:

class Person {
    String name
    Date dateOfBirth

    static constraints = {
    }
}

Map  people = [:]
[*(11..20), *(1..10)].each {
    Person person = new Person()
    person.name = "Person-" + it
    use(org.codehaus.groovy.runtime.TimeCategory) {
        person.dateOfBirth = new Date() - (new Random().nextInt(15) + 10).years
    }
    people[person.name] = person
}

Now, Sorting maps in ascending order is a simple one line code:

// Sort by Key(Person's Name):
map = map.sort {it.key}

// Sort by Value(Person Object):
map = map.sort {it.value}

// Sort by a particular field of Value(Date Of Birth):
map = map.sort {it.value.dateOfBirth}

But how about sorting in reverse order. It would have been great to have map.reverse() or map.reverseSort{} available in Groovy. Since none exists, I had to create the following method:

Map reverseSortMap(Map unsortedMap) {

    // Different implementations of Comparator
    // 1. Reverse Sort by Key(Person's Name):
    Comparator comparator = [compare: {a , b ->
    b.compareTo(a)
    }] as Comparator

    // 2. Reverse Sort by Value(Person Object):
    Comparator comparator = [compare: {a , b ->
    unsortedMap.get(b).compareTo(unsortedMap.get(a))
    }] as Comparator

    // 3. Reverse Sort by a particular field of Value(Date Of Birth):
    Comparator comparator = [compare: {a , b ->
    unsortedMap.get(b).dateOfBirth.compareTo(unsortedMap.get(a).dateOfBirth)
    }] as Comparator

    Map sortedMap = new TreeMap(comparator)
    sortedMap.putAll(unsortedMap)

    return sortedMap
}

Use either of the Comparator implementations above & use the method:

people = reverseSortMap(people)

Hope it helps.


~Aman Aggarwal
aman@intelligrape.com

http://www.IntelliGrape.com/

FOUND THIS USEFUL? SHARE IT

comments (6)

  1. Tim Yates

    Can’t you just do:

    people.sort { a, b -> b.value.dateOfBirth a.value.dateOfBirth }

    Or am I missing the point?

    Reply
  2. Paul King

    Groovy 1.6.1 offers some additional possibilities:

    def m = [a:1, b:3, c:2]
    println [:] + m.entrySet().sort{it.value}.reverse()
    println [:].putAll(m.entrySet().sort{it.key}.reverse())

    Reply

Leave a comment -