public static Map groupBy(Iterable self, Object... closures) {
        final Closure head = closures.length == 0 ? Closure.IDENTITY : (Closure) closures[0];

        @SuppressWarnings("unchecked")
        Map<Object, List> first = groupBy(self, head);
        if (closures.length < 2)
            return first;

        final Object[] tail = new Object[closures.length - 1];
        System.arraycopy(closures, 1, tail, 0, closures.length - 1); // Arrays.copyOfRange only since JDK 1.6

        // inject([:]) { a,e {@code ->} a {@code <<} [(e.key): e.value.groupBy(tail)] }
        Map<Object, Map> acc = new LinkedHashMap<Object, Map>();
        for (Map.Entry<Object, List> item : first.entrySet()) {
            acc.put(item.getKey(), groupBy((Iterable)item.getValue(), tail));
        }

        return acc;
    }
public static Map groupBy ( Iterable self , Object ... closures ) { final Closure head = closures . length == 0 ? Closure . IDENTITY : ( Closure ) closures [ 0 ] ; @ SuppressWarnings ( "unchecked" ) Map < Object , List > first = groupBy ( self , head ) ; if ( closures . length < 2 ) return first ; final Object [ ] tail = new Object [ closures . length - 1 ] ; System . arraycopy ( closures , 1 , tail , 0 , closures . length - 1 ) ; Map < Object , Map > acc = new LinkedHashMap < Object , Map > ( ) ; for ( Map . Entry < Object , List > item : first . entrySet ( ) ) { acc . put ( item . getKey ( ) , groupBy ( ( Iterable ) item . getValue ( ) , tail ) ) ; } return acc ; }
Sorts all Iterable members into (sub)groups determined by the supplied
mapping closures. Each closure should return the key that this item
should be grouped by. The returned LinkedHashMap will have an entry for each
distinct 'key path' returned from the closures, with each value being a list
of items for that 'group path'.

Example usage:
<pre class="groovyTestCase">def result = [1,2,3,4,5,6].groupBy({ it % 2 }, { it {@code <} 4 })
assert result == [1:[(true):[1, 3], (false):[5]], 0:[(true):[2], (false):[4, 6]]]</pre>

Another example:
<pre>def sql = groovy.sql.Sql.newInstance(/&ast; ... &ast;/)
def data = sql.rows("SELECT * FROM a_table").groupBy({ it.column1 }, { it.column2 }, { it.column3 })
if (data.val1.val2.val3) {
// there exists a record where:
//   a_table.column1 == val1
//   a_table.column2 == val2, and
//   a_table.column3 == val3
} else {
// there is no such record
}</pre>
If an empty array of closures is supplied the IDENTITY Closure will be used.

@param self     a collection to group
@param closures an array of closures, each mapping entries on keys
@return a new Map grouped by keys on each criterion
@since 2.2.0
@see Closure#IDENTITY