Groovy Maps: Reverse Sort
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
Thanks – this was helpful!
Thanks Paul King
“[:].sort{it.value}.reverse()”
is what I was looking for
Yes it works like charm.. Didn’t know that..
Thanks
*sigh* missed the operators…
people.sort { a, b -> b.value.dateOfBirth <=> a.value.dateOfBirth }
Can’t you just do:
people.sort { a, b -> b.value.dateOfBirth a.value.dateOfBirth }
Or am I missing the point?
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())