We can group elements in a List or Map with the groupBy()
method for a long time in Groovy. We pass a closure with the grouping condition to get a Map with the items grouped. And since Groovy 1.8.1 we can use more than closure to do the grouping. We can use it for both List and Map objects.
import static java.util.Calendar.* class User { String name String city Date birthDate public String toString() { name } } def users = [ new User(name:'mrhaki', city: 'Tilburg', birthDate: Date.parse('yyyy-MM-dd', '1973-9-7')), new User(name:'bob', city: 'New York', birthDate: Date.parse('yyyy-MM-dd', '1963-3-30')), new User(name:'britt', city: 'Amsterdam', birthDate: Date.parse('yyyy-MM-dd', '1980-5-12')), new User(name:'kim', city: 'Amsterdam', birthDate: Date.parse('yyyy-MM-dd', '1983-3-30')), new User(name:'liam', city: 'Tilburg', birthDate: Date.parse('yyyy-MM-dd', '2009-3-6')) ] def result = users.groupBy({it.city}, {it.birthDate.format('MMM')}) assert result.toMapString() == '[Tilburg:[Sep:[mrhaki], Mar:[liam]], New York:[Mar:[bob]], Amsterdam:[May:[britt], Mar:[kim]]]' assert result.Amsterdam.size() == 2 assert result.Tilburg.Mar.name == ['liam'] result = users.groupBy({it.name[0]}, {it.city}) assert result.toMapString() == '[m:[Tilburg:[mrhaki]], b:[New York:[bob], Amsterdam:[britt]], k:[Amsterdam:[kim]], l:[Tilburg:[liam]]]' assert result.k.Amsterdam.name == ['kim'] // groupBy with multiple closues also works on Map def usersByCityMap = users.groupBy({it.city}) def resultMap = usersByCityMap.groupBy({it.value.size()}, { k,v -> k.contains('i') }) assert resultMap.toMapString() == '[2:[true:[Tilburg:[mrhaki, liam]], false:[Amsterdam:[britt, kim]]], 1:[false:[New York:[bob]]]]' assert resultMap[1].size() == 1 assert resultMap[2].size() == 2 assert resultMap[2][true].Tilburg.name.join(',') == 'mrhaki,liam'
Test the code on Groovy web console.