Groovy는 List, Map, 배열(arrays)과 같은 콜랙션에 대해 언어 차원에서 지원하고 있습니다.

List

List는 다음과 같이 만들 수 있습니다 [] 는 빈 List를 의미합니다:

def list = [5, 6, 7, 8]
assert list.get(2) == 7
assert list[2] == 7
assert list instanceof java.util.List

def emptyList = []
assert emptyList.size() == 0
emptyList.add(5)
assert emptyList.size() == 1

각 List 표현식은 java.util.List 를 구현하는 객체를 생성합니다.

Range

Range는 연속된 값들을 생성해내며, List와 마찬가지로 쓰일 수 있습니다.

{link:Range|http://groovy.codehaus.org/apidocs/groovy/lang/Range.html}{link}
java.util.List 를 확장하고 있습니다.
.. 표기법으로 정의된 Range는 범위의 첫 값과 끝 값을 모두 포함하는 객체를 만들고 ..< 표기법으로 정의된 Range는 범위의 첫 값은 포함하지만 끝 값은 포함하지 않는 객체를 만들어냅니다.

// 포함적 Range
def range = 5..8
assert range.size() == 4
assert range.get(2) == 7
assert range[2] == 7
assert range instanceof java.util.List
assert range.contains(5)
assert range.contains(8)

// 배제적(exclusive) Range
range = 5..<8
assert range.size() == 3
assert range.get(2) == 7
assert range[2] == 7
assert range instanceof java.util.List
assert range.contains(5)
assert ! range.contains(8)

Range는 from과 to에 해당하는 값 두 개만을 갖는 매우 효율적인 객체로 구현됩니다.

Range는 비교를 위해 java.lang.Comparable 를 구현하고 있고, 이전 값과 다음 값을 반환하는 next(), previous() 메서드를 제공하는 어떠한 객체에 대해서도 사용될 수 있습니다. 예를 들어, 문자열도 사용할 수 있습니다.

// an inclusive range
def range = 'a'..'d'
assert range.size() == 4
assert range.get(2) == 'c'
assert range[2] == 'c'
assert range instanceof java.util.List
assert range.contains('a')
assert range.contains('d')
assert ! range.contains('e')

Range는 또한 for 문에서도 사용할 수 있습니다:

for (i in 1..10) {
  println "Hello ${i}"
}

Map

Map은 다음 문법을 통해 만들 수 있습니다. [:] 표현은 빈 Map을 만들어냅니다.

def map = [name:"Gromit", likes:"cheese", id:1234]
assert map.get("name") == "Gromit"
assert map.get("id") == 1234
assert map["name"] == "Gromit"
assert map['id'] == 1234
assert map instanceof java.util.Map

def emptyMap = [:]
assert emptyMap.size() == 0
emptyMap.put("foo", 5)
assert emptyMap.size() == 1
assert emptyMap.get("foo") == 5

Map은 Bean 처럼 쓸 수도 있습니다. 따라서 Map에 들어있는 Key가 유효한 Groovy 식별자인 경우 아이템을 넣거나 얻어오기 위해 속성(property)에 접근하는 문법을 그대로 쓸 수 있습니다.

def map = [name:"Gromit", likes:"cheese", id:1234]
assert map.name == "Gromit"
assert map.id == 1234

def emptyMap = [:]
assert emptyMap.size() == 0
emptyMap.foo = 5
assert emptyMap.size() == 1
assert emptyMap.foo == 5

비고: 설계상, map.foo는 언제나 map에 들어있는 foo라는 Key를 찾습니다. 즉 빈 Map인 경우 foo.class 는 getClass()를 호출하지 않고 null을 반환할 것입니다.

첨자 연산자를 이용해 자르기

String, List, 배열, Map, 정규식 등에서 특정 요소를 뽑아오기 위해 첨자 표현을 사용할 수 있습니다:

def text = "nice cheese gromit!"
def x = text[2]

assert x == "c"
assert x.class == String

def sub = text[5..10]
assert sub == 'cheese'

def map = [name:"Gromit", likes:"cheese", id:1234]

assert map["name"] == "Gromit"
assert map.name == "Gromit"

def list = [10, 11, 12]
def answer = list[2]
assert answer == 12

List/배열/String/정규식의 일부분을 뽑아내기 위해 Range를 사용할 수도 있습니다. Python 같은 스크립트 언어에서는 이를 잘라내기(slicing)라고 부릅니다:

def list = 100..200
def sub = list[1, 3, 20..25, 33]
assert sub == [101, 103, 120, 121, 122, 123, 124, 125, 133]

아이템을 갱신할 수도 있습니다:

def list = ["a", "b", "c"]
list[2] = "d"
list[0] = list[1]
list[3] = 5
assert list == ["b", "b", "d", 5]

끝에서부터 인덱싱을 하기 위해 음수를 쓸 수도 있습니다:

def text = "nice cheese gromit!"
def x = text[-1]
assert x == "!"

def name = text[-7..-2]
assert name == "gromit"

큰 수에서 작은 수로 줄어드는 Range를 사용하면 그 결과 또한 뒤집어집니다:

def text = "nice cheese gromit!"
def name = text[3..1]
assert name == "eci"

동적 객체 (Expando)

Expando는 엄밀히 말해서 콜랙션은 아닙니다. 하지만 Map 혹은 Javascript에서의 Object와 비슷합니다. Expando 를 이용하면 클로저 를 통해 객체에 메서드를 등록할 수가 있습니다:

def player = new Expando()
player.name = "Dierk"
player.greeting = { "Hello, my name is $name" }

println player.greeting()
player.name = "Jochen"
println player.greeting()

player.greeting 에 할당된 클로저Expando 에 대해 greeting() 이 호출될 때 실행됩니다. 할당된 클로저는 GString 의 "$variableOrProperty" 표기법을 통해 객체의 속성에 접근할 수 있다는 사실에 주목하세요.