Dark theme | Light theme

September 11, 2015

Groovy Goodness: Removing Elements From a Collection

There are a lot of methods added to the Java collection classes by Groovy. For example to remove elements from a collection, and indeed modify the collection itself, we can use the removeAll and removeElement methods. With the removeAll method we define a closure with a condition that needs to be true for an element to be removed from the collection. The removeElement method is added to overcome any ambiguity with the standard overloaded remove method for collections with integer values. The remove method accepts both an Object or int value, to remove either an element or an element at the specified index. When the collection contains integer values than the argument is interpreted as index value. The removeElement method will use the remove(Object) method implementation. When the collection is a List Groovy adds the removeAt method. We need to specify the index value of the element we want to remove.

def list = ['Groovy', '=', 'gr8!']

// Groovy adds removeAll method
// to remove items from collection
// that apply to the condition we 
// define in the closure.
list.removeAll { it.toLowerCase().startsWith('g') }

// All values starting with a G or g
// are now removed.
// Remember the collection we use the
// removeAll method on is changed.
assert list == ['=']

// Java 8 adds removeIf method with
// a predicate. In Groovy we can implement
// the predicate as closure.
list.removeIf { it instanceof String }

assert list.size() == 0

def values = ['Hello', 'world']

// Groovy adds removeAll(Object[]) 
// to remove multiple elements
// from a collection.
values.removeAll(['world', 'Hello'] as Object[])

assert values.empty

def items = [1, 2, 3]

// remove method is overloaded
// for Object and index value.
// Because Groovy wraps int to
// Integer object, the method call
// is ambiguous for Integer collections.

// We want to remove object
// Integer(1) from the list,
// but item with index 1 is removed.
assert items == [1, 3]

// Groovy adds removeElement
// as alias for remove(Object).

assert items == [3]

// When the collection is a List
// we can use the removeAt method
// to remove based on index value.

assert !items

Instead of removing elements with a any of the remove... methods we can also use the retainAll method in Groovy. Any elements that don't apply to the condition we specify in the closure are removed from the collection. See the following example code with some usages of the retainAll methods:

def list = ['Groovy', 42, 'gr8!', 5.2, new Date()]

// Groovy adds retainAll method
// to remove items from collection
// that do not apply to the condition we 
// define in the closure and keep those
// items that do apply to the condition.
list.retainAll { it instanceof String }

// All values that are not a String
// object are removed.
// Remember the collection we use the
// retainAll method on is changed.
assert list == ['Groovy', 'gr8!']

def values = ['Hello', 'world', 'from', 'Groovy']

// Groovy adds retainAll(Object[]) 
// to keep multiple elements
// in a collection and remove all
// the other elements.
values.retainAll(['world', 'Hello'] as Object[])

assert values.join(' ') == 'Hello world'

Written with Groovy 2.4.4.