美文网首页
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