Groovy通过内置的方式对集合、列表、映射和数组提供支持。
你可以通过如下方式来创建一个列表,
注意[]是一个空列表。
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
每一个列表都是java.util.List的实现。
更多列表用法请参考Lists and Sets。
Ranges让你创建一系列值的列表,这些Ranges可以当作List来用,因为Range继承自java.util.List
用..标记定义的Ranges是包含边界的(即列表包含从开始到结束的值)。
用..<标记定义的Ranges是不包含边界的,它们包括开始值,但不包括最后那个值。
// an inclusive 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) // lets use an 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)
注意ranges的实现是高效的,它创建一个轻量级的包含开始和结束值的Java对象。
Ranges也可以被使用在任何实现了java.lang.Comparable接口的Java对象上(用于比较)和含有next()及previous()方法(用于返回下一个/前一个值)。比如你可以在Strings中使用range:
// 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')
Ranges可以被用在for语句的遍历中:
for (i in 1..10) { println "Hello ${i}" }
但是另外一种等效的方法是通过each方法来遍历range:
(1..10).each { i -> println "Hello ${i}" }
Ranges还可以在switch语句中使用:
switch (years) { case 1..10: interestRate = 0.076; break; case 11..25: interestRate = 0.052; break; default: interestRate = 0.037; }
映射可以通过如下实例的语法来创建,
注意[:]是一个空映射。
映射的键(key)缺省是字符串,因此[a:1]跟[“a”:1]是等价的,但有时候,你确实需要一个变量作为key,那你需要用括号括起来才行:[(a):1]。
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
映射也可以象beans的属性操作那样来使用,只要保证keys是字符串并且符合Groovy标识(一个合法的名字)即可。
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,这意味着在一个空映射中,foo.class将返回null而不是调用其方法getClass()。
关于映射的更多用法参考Maps
你可以通过下标来索引Strings、Lists、arrays、Maps、regexs等等。
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
注意
你可以使用ranges来提取List/array/String/regex中的一部分,这在其他脚本语言中比如Python是通过slicing来实现的,你也可以使用列表的index。
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]
你还可以用负的索引值,其意义是 List, array, String等的后边开始计算。
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并不是集合,但是在某些方面,它很像映射或者JavaScript的对象,它们都不需要提前定义属性,而且还可以通过使用Groovy的闭包机制来创建动态对象,Expando不同于映射之处是你可以在调用对象上提供方法的定义。
def player = new Expando() player.name = "Dierk" player.greeting = { "Hello, my name is $name" } println player.greeting() player.name = "Jochen" println player.greeting()
当Expando上的greeting() 被调用时,player.greeting就传一个闭包参数来执行。注意
在闭包中可以通过Groovy的GString的”$variableOrProperty” 标记来访问赋值给Expando的属性,虽然这些属性可能会变化。