文档
http://www.groovy-lang.org/groovy-dev-kit.html#_working_with_collections
1、 Lists
1.1 迭代
[1, 2, 3].each {
println "Item: $it"
}
['a', 'b', 'c'].eachWithIndex { it, index ->
println "$index : $it"
}
assert [1, 2, 3].collect { it * 2 } == [2, 4, 6]
assert [1, 2, 3]*.multiply(2) == [1, 2, 3].collect { it.multiply(2) }
1.2 操作列表
过滤和查找
// 查找第一个符合条件的元素
assert [1, 2, 3].find { it > 1 } == 2
// 查找符合条件的所有元素
assert [1, 2, 3].findAll { it > 1 } == [2, 3]
// 查找第一个符合条件的元素的index
assert ['a', 'b', 'c', 'd', 'e'].findIndexOf {
it in ['c', 'e', 'g']
} == 2
// 判断是否所有元素都符合条件
assert [1, 2, 3].every { it < 5 }
assert ![1, 2, 3].every { it < 3 }
// 判断是否有任意的元素符合条件
assert [1, 2, 3].any { it > 2 }
assert ![1, 2, 3].any { it > 3 }
// 使用 plus() 方法 sum 所有元素
assert [1, 2, 3, 4, 5, 6].sum() == 21
// 将元素的值转换成别的值进行sum
assert ['a', 'b', 'c', 'd', 'e'].sum {
it == 'a' ? 1 : it == 'b' ? 2 : it == 'c' ? 3 : it == 'd' ? 4 : it == 'e' ? 5 : 0
} == 15
assert ['a', 'b', 'c', 'd', 'e'].sum { ((char) it) - ((char) 'a') } == 10
assert ['a', 'b', 'c', 'd', 'e'].sum() == 'abcde'
assert [['a', 'b'], ['c', 'd']].sum() == ['a', 'b', 'c', 'd']
// 可以指定一个初始值
assert [].sum(1000) == 1000
assert [1, 2, 3].sum(1000) == 1006
// 连接字符串
assert [1, 2, 3].join('-') == '1-2-3'
assert [1, 2, 3].inject('counting: ') {
str, item -> str + item
} == 'counting: 123'
assert [1, 2, 3].inject(0) { count, item ->
count + item
} == 6
// 查找Collection中的最大值和最小值
def list = [9, 4, 2, 10, 5]
assert list.max() == 10
assert list.min() == 2
// 还可以比较单个字符,以及其他可以 comparable的对象
assert ['x', 'y', 'a', 'z'].min() == 'a'
// 还可以使用 closure 来指定sorting 规则
def list2 = ['abc', 'z', 'xyzuvw', 'Hello', '321']
assert list2.max { it.size() } == 'xyzuvw'
assert list2.min { it.size() } == 'z'
// 除了使用 closure之外,也可以使用 Comparator
Comparator mc = { a, b -> a == b ? 0 : (a < b ? -1 : 1) }
def list = [7, 4, 9, -6, -1, 11, 2, 3, -9, 5, -13]
assert list.max(mc) == 11
assert list.min(mc) == -13
增加或移除元素
def list = []
assert list.empty
list << 5
assert list.size() == 1
list << 7 << 'i' << 11
assert list == [5, 7, 'i', 11]
list << ['m', 'o']
assert list == [5, 7, 'i', 11, ['m', 'o']]
// 使用 leftShift 等价于使用 <<
assert ([1, 2, 3] << 4) == ([1, 2, 3].leftShift(4))
assert [1, 2] + 3 + [4, 5] + 6 == [1, 2, 3, 4, 5, 6]
// + 等价于使用 plus 方法
assert [1, 2].plus(3).plus([4, 5]).plus(6) == [1, 2, 3, 4, 5, 6]
assert [1, *[222, 333], 456] == [1, 222, 333, 456]
assert [*[1, 2, 3]] == [1, 2, 3]
assert [1, [2, 3, [4, 5], 6], 7, [8, 9]].flatten() == [1, 2, 3, 4, 5, 6, 7, 8, 9]
def list = [1, 2]
list.add(3)
list.addAll([5, 4])
assert list == [1, 2, 3, 5, 4]
list = ['a', 'b', 'z', 'e', 'u', 'v', 'g']
// [] 操作符会按需提升 list的size ,并填充必须的 nulls
list[8] = 'x'
assert list == ['a', 'b', 'z', 'e', 'u', 'v', 'g', null, 'x']
需要注意, +
会产生一个新的list,而 <<
改变原来的list
除了 +
, 还有 -
assert ['a','b','c','b','b'] - 'c' == ['a','b','b','b']
assert ['a','b','c','b','b'] - 'b' == ['a','c']
assert ['a','b','c','b','b'] - ['b','c'] == ['a']
def list = [1,2,3,4,3,2,1]
list -= 3
assert list == [1,2,4,2,1]
assert ( list -= [2,4] ) == [1,1]
// 也可以通过 remove 方法移除元素
def list = ['a','b','c','d','e','f','b','b','a']
// 移除第3个元素 并返回它
assert list.remove(2) == 'c'
assert list == ['a','b','d','e','f','b','b','a']
def list= ['a','b','c','b','b']
// 移除 c 元素 并返回 true,因为有元素被移除了
assert list.remove('c')
// 移除 第1个b元素,并返回true,因为有元素被移除了
assert list.remove('b')
// 返回false,因为没有元素被移除
assert ! list.remove('z')
assert list == ['a','b','b']
// 你可能已经注意到,这两个 remove 方法可能会存在冲突
// 实际上,当元素的类型为 int 型时,remove(int) 或 removeAt(index) 仍然表示按index移除元素
// 而 removeElement(Object)表示移除具体的元素
// 清空所有元素
def list= ['a',2,'c',4]
list.clear()
assert list == []
Set operations
assert 'a' in ['a','b','c']
assert ['a','b','c'].contains('a')
assert [1,3,4].containsAll([1,4])
assert [1,2,3,3,3,3,4,5].count(3) == 4
assert [1,2,3,3,3,3,4,5].count {
it%2==0
} == 2
assert [1,2,4,6,8,10,12].intersect([1,3,6,9,12]) == [1,6,12]
assert [1,2,3].disjoint( [4,6,9] )
assert ![1,2,3].disjoint( [2,4,6] )
Sorting
assert [6, 3, 9, 2, 7, 1, 5].sort() == [1, 2, 3, 5, 6, 7, 9]
def list = ['abc', 'z', 'xyzuvw', 'Hello', '321']
assert list.sort {
it.size()
} == ['z', 'abc', '321', 'Hello', 'xyzuvw']
def list2 = [7, 4, -6, -1, 11, 2, 3, -9, 5, -13]
assert list2.sort { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } ==
[-1, 2, 3, 4, 5, -6, 7, -9, 11, -13]
Comparator mc = { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 }
// JDK 8+ only
// list2.sort(mc)
// assert list2 == [-1, 2, 3, 4, 5, -6, 7, -9, 11, -13]
def list3 = [6, -3, 9, 2, -7, 1, 5]
Collections.sort(list3)
assert list3 == [-7, -3, 1, 2, 5, 6, 9]
Collections.sort(list3, mc)
assert list3 == [1, 2, -3, 5, 6, -7, 9]
Duplicating elements
assert [1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3]
assert [1, 2, 3].multiply(2) == [1, 2, 3, 1, 2, 3]
assert Collections.nCopies(3, 'b') == ['b', 'b', 'b']
// nCopies from the JDK has different semantics than multiply for lists
assert Collections.nCopies(2, [1, 2]) == [[1, 2], [1, 2]] //not [1,2,1,2]
2、Maps
2.1 迭代
def map = [
Bob : 42,
Alice: 54,
Max : 33
]
// `entry` is a map entry
map.each { entry ->
println "Name: $entry.key Age: $entry.value"
}
// `entry` is a map entry, `i` the index in the map
map.eachWithIndex { entry, index ->
println "$index - Name: $entry.key Age: $entry.value"
}
// Alternatively you can use key and value directly
map.each { key, value ->
println "Name: $key Age: $value"
}
// Key, value and i as the index in the map
map.eachWithIndex { key, value, i ->
println "$i - Name: $key Age: $value"
}
2.2 操作maps
增加或移除元素
def defaults = [1: 'a', 2: 'b', 3: 'c', 4: 'd']
def overrides = [2: 'z', 5: 'x', 13: 'x']
def result = new LinkedHashMap(defaults)
result.put(15, 't')
result[17] = 'u'
result.putAll(overrides)
assert result == [1: 'a', 2: 'z', 3: 'c', 4: 'd', 5: 'x', 13: 'x', 15: 't', 17: 'u']
def m = [1:'a', 2:'b']
assert m.get(1) == 'a'
m.clear()
assert m == [:]
Keys, values and entries
def map = [1:'a', 2:'b', 3:'c']
def entries = map.entrySet()
entries.each { entry ->
assert entry.key in [1,2,3]
assert entry.value in ['a','b','c']
}
def keys = map.keySet()
assert keys == [1,2,3] as Set
过滤和查找
def people = [
1: [name:'Bob', age: 32, gender: 'M'],
2: [name:'Johnny', age: 36, gender: 'M'],
3: [name:'Claire', age: 21, gender: 'F'],
4: [name:'Amy', age: 54, gender:'F']
]
// find a single entry
def bob = people.find { it.value.name == 'Bob' }
def females = people.findAll { it.value.gender == 'F' }
// both return entries, but you can use collect to retrieve the ages for example
def ageOfBob = bob.value.age
def agesOfFemales = females.collect {
it.value.age
}
assert ageOfBob == 32
assert agesOfFemales == [21,54]
// but you could also use a key/pair value as the parameters of the closures
def agesOfMales = people.findAll { id, person ->
person.gender == 'M'
}.collect { id, person ->
person.age
}
assert agesOfMales == [32, 36]
// `every` returns true if all entries match the predicate
assert people.every { id, person ->
person.age > 18
}
// `any` returns true if any entry matches the predicate
assert people.any { id, person ->
person.age == 54
}
Grouping分组
我们可以将 list 分组到 一个map
assert ['a', 7, 'b', [2, 3]].groupBy {
it.class
} == [(String) : ['a', 'b'],
(Integer) : [7],
(ArrayList): [[2, 3]]
]
assert [
[name: 'Clark', city: 'London'], [name: 'Sharma', city: 'London'],
[name: 'Maradona', city: 'LA'], [name: 'Zhang', city: 'HK'],
[name: 'Ali', city: 'HK'], [name: 'Liu', city: 'HK'],
].groupBy { it.city } == [
London: [[name: 'Clark', city: 'London'],
[name: 'Sharma', city: 'London']],
LA : [[name: 'Maradona', city: 'LA']],
HK : [[name: 'Zhang', city: 'HK'],
[name: 'Ali', city: 'HK'],
[name: 'Liu', city: 'HK']],
]
3、 Ranges
Ranges 允许你创建一个顺序值组成的list,可以作为 List
使用,因为Range继承子 java.util.List
Ranges 使用 ..
表示包含右边界的list
使用 ..<
表示半开list,即不包括右边界的list
// 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 a half-open 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)
//get the end points of the range without using indexes
range = 1..10
assert range.from == 1
assert range.to == 10
for (i in 1..10) {
println "Hello ${i}"
}
(1..10).each { i ->
println "Hello ${i}"
}
switch (years) {
case 1..10: interestRate = 0.076; break;
case 11..25: interestRate = 0.052; break;
default: interestRate = 0.037;
}
4、 增强语法
4.1 GPath支持
def listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22]]
assert listOfMaps.a == [11, 21] //GPath notation
assert listOfMaps*.a == [11, 21] //spread dot notation
listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22], null]
assert listOfMaps*.a == [11, 21, null] // caters for null values
assert listOfMaps*.a == listOfMaps.collect { it?.a } //equivalent notation
// But this will only collect non-null values
assert listOfMaps.a == [11,21]
4.2 Spread operator
assert [ 'z': 900,
*: ['a': 100, 'b': 200], 'a': 300] == ['a': 300, 'b': 200, 'z': 900]
//spread map notation in map definition
assert [*: [3: 3, *: [5: 5]], 7: 7] == [3: 3, 5: 5, 7: 7]
def f = { [1: 'u', 2: 'v', 3: 'w'] }
assert [*: f(), 10: 'zz'] == [1: 'u', 10: 'zz', 2: 'v', 3: 'w']
//spread map notation in function arguments
f = { map -> map.c }
assert f(*: ['a': 10, 'b': 20, 'c': 30], 'e': 50) == 30
f = { m, i, j, k -> [m, i, j, k] }
//using spread map notation with mixed unnamed and named arguments
assert f('e': 100, *[4, 5], *: ['a': 10, 'b': 20, 'c': 30], 6) ==
[["e": 100, "b": 20, "c": 30, "a": 10], 4, 5, 6]
4.3 *.
操作符
assert [1, 3, 5] == ['a', 'few', 'words']*.size()
class Person {
String name
int age
}
def persons = [new Person(name:'Hugo', age:17), new Person(name:'Sandra',age:19)]
assert [17, 19] == persons*.age
4.4 Slicing with the subscript operator
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 list = [10, 11, 12, 13]
def answer = list[2,3]
assert answer == [12,13]
list = 100..200
sub = list[1, 3, 20..25, 33]
assert sub == [101, 103, 120, 121, 122, 123, 124, 125, 133]
// 使用下标更新
list = ['a','x','x','d']
list[1..2] = ['b','c']
assert list == ['a','b','c','d']
// 使用负数的下标,表示从结尾向前索引
text = "nice cheese gromit!"
x = text[-1]
assert x == "!"
def name = text[-7..-2]
assert name == "gromit"
text = "nice cheese gromit!"
name = text[3..1]
assert name == "eci"
网友评论