Loading...

September 15, 2011

Groovy Goodness: Sort or Remove Duplicates without Changing the Original Collection

We can sort and remove duplicates from collections or arrays in Groovy for a long time. The sort() and unique() methods alter the original collection, so there is a big side effect. Since Groovy 1.8.1 we can use a boolean argument to indicate if we want to mutate the original collection or not. So now we can remove the side effect and leave the original collection or array unchanged.

The reverse() method also accepts this boolean argument since Groovy 1.8.1, but the default behavior was already to leave the original collection unchanged. Now we can explicitly tell the reverse() method to change the original collection.

class User implements Comparable {
    String username, email
    boolean active
    
    int compareTo(Object other) {
        username <=> other.username
    }
    
    String toString() { "[User:$username,$email,$active]" }
}

def mrhaki1 = new User(username: 'mrhaki', email: 'mrhaki@localhost', active: false)
def mrhaki2 = new User(username: 'mrhaki', email: 'user@localhost', active: true)

def hubert1 = new User(username: 'hubert', email: 'user@localhost', active: false)
def hubert2 = new User(username: 'hubert', email: 'hubert@localhost', active: true)

def users = [mrhaki1, mrhaki2, hubert1, hubert2]


/* Sort */
def sortedUsers = users.sort(mutate = false)  // Don't mutate original List
assert sortedUsers == [hubert1, hubert2, mrhaki1, mrhaki2]
assert users == [mrhaki1, mrhaki2, hubert1, hubert2]

// Default behaviour is to change original collection
sortedUsers = users.sort() 
assert sortedUsers == [hubert1, hubert2, mrhaki1, mrhaki2]
assert users == [hubert1, hubert2, mrhaki1, mrhaki2]


/* Unique */
def uniqueUsers = users.unique(mutate = false)  // Don't mutate original List
assert uniqueUsers == [hubert1, mrhaki1]
assert users == [hubert1, hubert2, mrhaki1, mrhaki2]

// Default behaviour is to change original collection
uniqueUsers = users.unique()   
assert uniqueUsers == [hubert1, mrhaki1]
assert users == [hubert1, mrhaki1]


/* Reverse */
def reverseUsers = users.reverse()  // mutate false is default
assert reverseUsers == [mrhaki1, hubert1]
assert users == [hubert1, mrhaki1]

// Default behaviour is to leave original collection alone
reverseUsers = users.reverse(mutate = true)  // Mutate original list
assert reverseUsers == [mrhaki1, hubert1]
assert users == [mrhaki1, hubert1]

You can try this code in Groovy web console.