Groovy

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, setsmaps, 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 closure
  • find{Closure} – finds the first item matching the closure condition
  • findAll() – finds all items matching the IDENTITY closure
  • findAll{Closure} – finds all items matching the closure condition
  • findResult{Closure} – finds the first non-null result matching the closure condition
  • findResult{Object, Closure} – finds the first non-null result matching the closure condition with a default result
  • grep() – finds all elements which satisfies Groovy truth
  • grep(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 with Closure.IDENTITY
  • collect(Closure transform) – iterates through the collection transforming each element into new value using closure
  • collect(Collection collector, Closure transform) – iterates through the collection transforming each element into new value using closure and adding it to the supplied collector.
  • each – iterates through the collection, passing each item to the given closure. Please check out my other article for a demonstration of each 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 Set
  • toList() – convert an Iterable to a List
  • toArray() – returns an array with all the elements in this collection in the same sequence order
  • toSpreadMap() – creates a spreadable map from this Iterable 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 collections
  • flatten{Closure} – return a new collection with flattened items
  • split{Closure} – splits all items into two collections based on the closure
  • sort() – modifies all the elements in sorted order
  • toSorted{Closure} – sorts all the elements and returns sorted list
  • groupby{Closure} – sorts all elements into groups by the mapping closure
  • countby{Closure} – sorts all elements into groups by the mapping closure and the counts of the group size
  • removeAll{Closure} -modifies the collection by removing the elements matching the closure
  • addAll(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:

Groovy Collection Unit Tests 2

Groovy Collection Unit Tests

5. Groovy Collections – Summary

In this example, we demonstrated Groovy Collection libraries to find, sort, and manipulate items in a collection of listmapset, 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.

Download
You can download the full source code of this example here: Groovy Collections Example

Mary Zheng

Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button