美文网首页
Working with collections

Working with collections

作者: 坚持到底v2 | 来源:发表于2018-03-27 14:36 被阅读0次

文档

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"

相关文章

网友评论

      本文标题:Working with collections

      本文链接:https://www.haomeiwen.com/subject/pffscftx.html