Groovy Collections Example
1. Introduction
Apache Groovy (Groovy) is an object-oriented dynamic programming language for the Java platform. It is dynamically compiled to the Java Virtual Machine (JVM) bytecode, and inter-operates with other Java source codes and libraries. Groovy is written in Java and was first released in 2007.
Groovy provides native support for various collection types, including lists, sets, maps, and ranges. Most of these are based on the Java collection types and decorated with additional methods found in the Groovy development kit.
In this example, I will demonstrate how to use Groovy Collection
interface to search, iterate, convert, and manipulate the elements in a collection.
2. Technologies Used
The example code in this article was built and run using:
- Java 1.8.101 (1.8.x will do fine)
- Maven 3.3.9 (3.3.x will do fine)
- Eclipse Mars (Any Java IDE would work)
- Groovy 2.4
3. Maven Project
A collection is an object that groups multiple elements into a single unit. It can be used to store, manipulate, retrieve, and communicate data. In this example, we will build unit test classes to demonstrate how to find, sort, split, and group elements.
3.1 Dependencies
We will add Groovy dependency in the pom.xml
.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jcg-zheng-demo</groupId> <version>1.0.0-SNAPSHOT</version> <artifactId>groovy-demo</artifactId> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.13</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>
3.2 Searching
Groovy Collection
interface defines several searching methods:
find()
– finds the first item matching the IDENTITY closurefind{Closure}
– finds the first item matching the closure conditionfindAll()
– finds all items matching the IDENTITY closurefindAll{Closure}
– finds all items matching the closure conditionfindResult{Closure}
– finds the first non-null result matching the closure conditionfindResult{Object, Closure}
– finds the first non-null result matching the closure condition with a default resultgrep()
– finds all elements which satisfies Groovy truthgrep(Object)
– finds all elements that matches the given filter
In this step, we will create a groovy unit test class Demo_Find
to show how to find desired items in a List
, Set
, Map
, or Range
.
Demo_Find.groovy
package jcg.zheng.demo.groovy import static org.junit.Assert.* import org.junit.Test class Demo_Find { @Test public void find_element_from_array_with_matching_value(){ String[] names = ["Mary", "Becky", "Susan", "Tom"] String foundByName = names.find { it.equalsIgnoreCase("mary") } assertEquals("Mary", foundByName) } @Test public void find_element_from_map_with_matching_key(){ def mymap = [name:"Mary", likes:"coding", id:1, comment:"Fun to hang out"] def likesValue = mymap.find{ it.key == "likes" }.value assertEquals("coding", likesValue) println likesValue } @Test public void find_element_from_list_with_matching_value(){ List names = ["Mary", "Becky", "Susan", "Tom"] String foundByName = names.find { it.equalsIgnoreCase("mary")} assertEquals("Mary", foundByName) } @Test public void find_person_from_array_with_matching_firstName(){ Person [] persons = [new Person("Mary", "Zheng"), new Person("Alex", "Zheng"), new Person("Allen", "Zheng")] Person found = persons.find { it.firstName == "Mary"} assertEquals("Mary", found.firstName) assertEquals("Zheng", found.lastName) } @Test public void find_evenNumbers_from_range_use_containAll_to_verify(){ def numbers = (1..10) List evenNumbers = numbers.findAll {it % 2 == 0} print evenNumbers List evenNumberUnderTen = [2, 4, 6, 8, 10] assertTrue(evenNumberUnderTen.containsAll(evenNumbers)) } @Test public void findResults_from_list_with_matching_condition(){ List names = ["Mary", "Becky", "Susan", "Tom"] String foundByName = names.findResult { if (it.startsWith("B")) it.toUpperCase()} assertEquals("BECKY", foundByName) } @Test public void grep_from_set_with_verify_with_equals(){ Set names = new HashSet() names.add("Zhang") names.add("Mary") names.add("Mary") names.add("Zheng") Set foundNameWithH = names.grep{it.contains("h")} assertEquals(2, foundNameWithH.size()) def hnames = ["Zhang", "Zheng"] as Set assertTrue(foundNameWithH.equals(hnames)) println foundNameWithH } @Test public void grep_object_from_set(){ Set mySet = [10, 20, 0, false, true, 'hello', [1, 2], [3, 4], null, "world"] println mySet.grep(Number) println mySet.grep(String) println mySet.grep(Boolean) println mySet.grep(Collection) println mySet.grep('hello') } }
3.3 Iteration
Groovy Collection
interface defines looping methods:
collect()
– iterates through the collection transforming each element into new value withClosure.IDENTITY
collect(Closure transform)
– iterates through the collection transforming each element into new value using closurecollect(Collection collector, Closure transform)
– iterates through the collection transforming each element into new value using closure and adding it to the suppliedcollector
.each
– iterates through the collection, passing each item to the given closure. Please check out my other article for a demonstration ofeach
method.
In this step, we will create a groovy unit test class Demo_Loop
to show how to iterate a collection of List
and Range
.
Demo_Loop.groovy
package jcg.zheng.demo.groovy import static org.junit.Assert.* import org.junit.Test class Demo_Loop { @Test public void loop_each_range_with_print(){ def numbers = (1..10) numbers.each { println it } } @Test public void loop_eachWithIndex_range_with_print(){ def numbers = (1..10) numbers.eachWithIndex { number, i -> println "${i} = ${number}"} } @Test public void when_collect_it_returns_new_collection_with_closure(){ def fruits = ["Banana", "Apple", "Grape", "Pear"] List upperCaseFruits = fruits.collect { it.toUpperCase() } assertEquals("BANANA", upperCaseFruits.get(0)) assertEquals("APPLE", upperCaseFruits.get(1)) assertEquals("GRAPE", upperCaseFruits.get(2)) assertEquals("PEAR", upperCaseFruits.get(3)) println upperCaseFruits } @Test public void when_collect_with_default_it_returns_new_collection_with_closure(){ def initialFruits = ["ORANGE", "LEMON"] def fruits = ["Banana", "Apple", "Grape", "Berry"] def totalFruits = fruits.collect(initialFruits, { it.toUpperCase() }) println totalFruits //[ORANGE, LEMON, BANANA, APPLE, GRAPE, BERRY] } }
3.4 Convert
Groovy Collection
and Iterable
interfaces define several converting methods:
toSet()
– convert a Collection to a SettoList()
– convert anIterable
to a ListtoArray()
– returns an array with all the elements in this collection in the same sequence ordertoSpreadMap()
– creates a spreadable map from thisIterable
object
In this step, we will create a groovy unit test class Demo_Convert
to show how to convert a collection as List
and Set
.
Demo_Convert.groovy
package jcg.zheng.demo.groovy import static org.junit.Assert.* import org.junit.Test class Demo_Convert { @Test public void convert_from_List_to_Set_duplicate_element_is_gone(){ List names = ["Mary", "Becky", "Susan", "Tom", "Mary"] assertEquals(5, names.size()) Set nameSet = names.toSet() assertEquals(4, nameSet.size()) println nameSet } @Test public void convert_from_List_to_String(){ List names = ["Mary", "Becky", "Susan", "Tom"] String nameValues = names.toListString() assertEquals("[Mary, Becky, Susan, Tom]", nameValues) println nameValues } @Test public void convert_from_List_to_Array(){ List names = ["Mary", "Becky", "Susan", "Tom", "Mary"] assertEquals(5, names.size()) String[] nameArray = names.toArray() assertEquals(5, nameArray.size()) println nameArray } @Test public void covert_from_evenNumber_list_to_map_with_toSpreadMap(){ def evenNumberList = ['key', 'value', 'name', 'mary', 'age', '40'] as Object[] def map = evenNumberList.toSpreadMap() assert 3 == map.size() assert 'value' == map.key assert 'mary' == map['name'] assert '40' == map['age'] } }
3.5 Manipulation
Groovy Collection
and Iterable
interfaces define lots of methods to manipulate elements in a collection. In this step, we will demonstrate below common methods:
intersect(Collection)
– create a collection composed of the intersection of both collectionsflatten{Closure}
– return a new collection with flattened itemssplit{Closure}
– splits all items into two collections based on the closuresort()
– modifies all the elements in sorted ordertoSorted{Closure}
– sorts all the elements and returns sorted listgroupby{Closure}
– sorts all elements into groups by the mapping closurecountby{Closure}
– sorts all elements into groups by the mapping closure and the counts of the group sizeremoveAll{Closure}
-modifies the collection by removing the elements matching the closureaddAll(Object)
– adds all the items from the given object to the collection
In this step, we will create a groovy unit test class Demo_Manipulate
to show how to add, remove, sort, split, group, and flatten elements in a collection of List
, Set
, and Range
.
Demo_Manipulate.groovy
package jcg.zheng.demo.groovy import static org.junit.Assert.* import org.junit.Test class Demo_Manipulate { @Test public void when_sort_array_then_modify_array_to_sorted_order(){ String[] names = ["Mary", "Becky", "Susan", "Tom"] println names assertEquals(4, names.size()) assertEquals("Mary", names[0]) assertEquals("Becky", names[1]) assertEquals("Susan", names[2]) assertEquals("Tom", names[3]) names.sort() assertEquals("Becky", names[0]) assertEquals("Mary", names[1]) assertEquals("Susan", names[2]) assertEquals("Tom", names[3]) println "Sorted name: " println names } @Test public void when_tosort_array_then_array_is_not_modified_but_new_sorted_array_is_returned(){ String[] names = ["Mary", "Becky", "Susan", "Tom"] println names assertEquals(4, names.size()) assertEquals("Mary", names[0]) assertEquals("Becky", names[1]) assertEquals("Susan", names[2]) assertEquals("Tom", names[3]) def sortedNames = names.toSorted() assertEquals("Becky", sortedNames[0]) assertEquals("Mary", sortedNames[1]) assertEquals("Susan", sortedNames[2]) assertEquals("Tom", sortedNames[3]) println "Sorted name: " println names } @Test public void when_sort_list_then_the_list_is_modified_in_sorted_order(){ List names = ["Mary", "Becky", "Susan", "Tom"] assertEquals(4, names.size()) assertEquals("Mary", names[0]) assertEquals("Becky", names[1]) assertEquals("Susan", names[2]) assertEquals("Tom", names[3]) names.sort() assertEquals("Becky", names[0]) assertEquals("Mary", names[1]) assertEquals("Susan", names[2]) assertEquals("Tom", names[3]) println "Sorted name: " names.each { print "${it}, "} } @Test public void when_sort_persons_the_persons_not_modified_but_new_sorted_persons_is_returned(){ Person[] persons = [new Person("Mary", "Zheng"), new Person("Alex", "Zheng"), new Person("Allen", "Zheng")] assertEquals("Mary", persons[0].firstName) assertEquals("Alex", persons[1].firstName) assertEquals("Allen", persons[2].firstName) def orderByFirstName = persons.sort { it.firstName } assertEquals("Alex", orderByFirstName[0].firstName) assertEquals("Allen", orderByFirstName[1].firstName) assertEquals("Mary", orderByFirstName[2].firstName) orderByFirstName.each { println it } } @Test public void when_sort_set_the_set_not_modified_but_new_sorted_set_is_returned(){ Set names = new HashSet() names.add("Zhang") names.add("Mary") names.add("Zheng") Set orderSet = names.sort() orderSet.eachWithIndex { name, i -> println "${i} = '${name}'"} } @Test public void when_groupby_list_with_matching_condition_it_returned_map_with_groupby_data(){ List names = ["Mary", "Becky", "Susan", "Tom"] Map<Boolean, List> hasY = names.groupBy{it.contains("y")} assertEquals(2, hasY.size()) assertTrue(hasY.keySet().contains(true)) assertTrue(hasY.keySet().contains(false)) assertEquals(2, hasY.get(true).size()) assertTrue(hasY.get(true).contains("Becky")) assertTrue(hasY.get(true).contains("Mary")) assertEquals(2, hasY.get(false).size()) assertTrue(hasY.get(false).contains("Susan")) assertTrue(hasY.get(false).contains("Tom")) println "\nGroup by name contains 'Y' or not: " hasY.each { println "${it.key}-${it.value}" } } @Test public void when_countby_list_with_matching_condition_it_returned_map_with_countby_count(){ List names = ["Mary", "Becky", "Susan", "Tom"] Map hasY = names.countBy{it.contains("T")} assertEquals(2, hasY.size()) assertTrue(hasY.keySet().contains(true)) assertTrue(hasY.keySet().contains(false)) assertEquals(1, hasY.get(true)) assertEquals(3, hasY.get(false)) println "\nCount by name contains 'T' or not: " hasY.each { println "${it.key}-${it.value}" } } @Test public void when_groupBy_it_returns_map_with_groupBy_data(){ def numbers = (1..50) def sameUnitsDigits = numbers.groupBy{it%10} sameUnitsDigits.each { println it} } @Test public void when_split_set_it_returns_map_of_two_sets(){ Set mySet = [100, 200, 300, 400, 500, 600] println mySet.split{it> 300} } @Test public void when_flatten_set_it_becomes_one_big_flat_set(){ Set foodSet = [["apple", "banana"], "peas", "green beans", ["egg", "milk", ["cheess", "ice cream"]]] assertEquals(4, foodSet.size()) Set flattenSet = foodSet.flatten() assertEquals(8, flattenSet.size()) println flattenSet } @Test public void when_intersect_set_it_finds_common_elements(){ Set firstSet = [1, 2, 3, 4, 5] Set secondSet = [4, 5, 6, 7, 8] Set intersectSet = firstSet.intersect(secondSet) assertEquals(2, intersectSet.size()) def commonNumbers = [4, 5] as Set assertTrue(commonNumbers.equals(intersectSet)) println intersectSet } @Test public void when_removeAll_it_becomes_empty(){ Set initialSet = [1, 2, 3, 4, 5] initialSet.removeAll([1, 2, 3, 4, 5]) assertTrue(initialSet.size() == 0) } @Test public void demo_addAll_and_unique_list(){ List names = ["Mary", "Becky", "Susan", "Tom"] names.addAll(["Mary", "Susan"]) assertEquals(6, names.size()) names.unique(); assertEquals(4, names.size()) println names } }
4. Demo
Execute all unit tests:
5. Groovy Collections – Summary
In this example, we demonstrated Groovy Collection libraries to find, sort, and manipulate items in a collection of list
, map
, set
, and range
.
6. Download the Source Code
This example consists of a Maven project which demonstrates the usage of Groovy Collection
‘s find
, sort
, split
, groupby
, etc, methods to search, iterate, convert, and manipulate elements in a collection.
You can download the full source code of this example here: Groovy Collections Example