Groovy는 List, Map, 배열(arrays)과 같은 콜랙션에 대해 언어 차원에서 지원하고 있습니다.
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는 연속된 값들을 생성해내며, List와 마찬가지로 쓰일 수 있습니다.
{link:Range|http://groovy.codehaus.org/apidocs/groovy/lang/Range.html}{link} |
// 포함적 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을 만들어냅니다.
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는 엄밀히 말해서 콜랙션은 아닙니다. 하지만 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" 표기법을 통해 객체의 속성에 접근할 수 있다는 사실에 주목하세요.