1.字面量

您可以按如下方式创建列表。请注意,这[]是空列表表达式。

  1. def list = [5, 6, 7, 8]
  2. assert list.get(2) == 7
  3. assert list[2] == 7
  4. assert list instanceof java.util.List
  5. def emptyList = []
  6. assert emptyList.size() == 0
  7. emptyList.add(5)
  8. assert emptyList.size() == 1

每个列表表达式创建一个java.util.List的实现。
当然列表可以用作构建另一个列表的源:

def list1 = ['a', 'b', 'c']
// 构建一个新的列表,其中包含与list1中相同的项目
def list2 = new ArrayList<String>(list1)

assert list2 == list1 // == 检查每个对应的元素是否相同

// 也可以调用clone()
def list3 = list1.clone()
assert list3 == list1

列表是对象的有序集合:

def list = [5, 6, 7, 8]
assert list.size() == 4
assert list.getClass() == ArrayList     // 正在使用的特定列表类型

assert list[2] == 7                     // 索引从0开始
assert list.getAt(2) == 7               // 下标索引[]的等价方法
assert list.get(2) == 7                 // 替代方法

list[2] = 9
assert list == [5, 6, 9, 8,]           // 尾随逗号OK

list.putAt(2, 10)                       // 值更改时与[]等效的方法
assert list == [5, 6, 10, 8]
assert list.set(2, 11) == 10            // 返回旧值的替代方法
assert list == [5, 6, 11, 8]

assert ['a', 1, 'a', 'a', 2.5, 2.5f, 2.5d, 'hello', 7g, null, 9 as byte]
// 对象可以是不同的类型;允许重复

assert [1, 2, 3, 4, 5][-1] == 5             // 使用负索引从末尾开始计数
assert [1, 2, 3, 4, 5][-2] == 4
assert [1, 2, 3, 4, 5].getAt(-2) == 4       // getAt() 可以用于负数索引...
try {
    [1, 2, 3, 4, 5].get(-2)                 // 但是 get() 不允许使用负数索引
    assert false
} catch (e) {
    assert e instanceof IndexOutOfBoundsException
}

2.作为Boolean表达式

列表可以作为一个boolean值来评估:

assert ![]             // 空列表的计算结果为 false

// 所有其他列表,无论内容如何,评估为 true
assert [1] && ['a'] && [0] && [0.0] && [false] && [null]

3.迭代

对列表元素的迭代通常通过调用eacheachWithIndex方法来完成,这些方法在列表的每个项目上执行代码:

[1, 2, 3].each {
    println "Item: $it" // `it` 是对应于当前元素的隐式参数
}
['a', 'b', 'c'].eachWithIndex { it, i -> // `it` 是当前元素,而`i`是索引
    println "$i: $it"
}

除了迭代之外,通过将每个元素转换为其他元素来创建新列表通常很有用。这个操作,通常称为映射,是在 Groovy 中完成的,这要归功于以下collect方法:

assert [1, 2, 3].collect { it * 2 } == [2, 4, 6]

// 快捷语法的 collect
assert [1, 2, 3]*.multiply(2) == [1, 2, 3].collect { it.multiply(2) }

def list = [0]
// 可以给`collect`一个收集元素的列表
assert [1, 2, 3].collect(list) { it * 2 } == [0, 2, 4, 6]
assert list == [0, 2, 4, 6]

4.操作

4.1.过滤和搜索

Groovy 开发工具包包含许多关于集合的方法,这些方法通过实用的方法增强标准集合,其中一些在此处进行了说明:

assert [1, 2, 3].find { it > 1 } == 2           // 查找第一个元素匹配条件
assert [1, 2, 3].findAll { it > 1 } == [2, 3]   // 查找与临界值匹配的所有元素
assert ['a', 'b', 'c', 'd', 'e'].findIndexOf {      // 查找第一个元素匹配条件的索引
    it in ['c', 'e', 'g']
} == 2

assert ['a', 'b', 'c', 'd', 'c'].indexOf('c') == 2  // 返回的索引
assert ['a', 'b', 'c', 'd', 'c'].indexOf('z') == -1 // 索引-1表示不在列表中的值
assert ['a', 'b', 'c', 'd', 'c'].lastIndexOf('c') == 4

assert [1, 2, 3].every { it < 5 }               // 如果所有元素都与条件匹配,则返回true
assert ![1, 2, 3].every { it < 3 }
assert [1, 2, 3].any { it > 2 }                 // 如果存在元素与条件匹配,则返回true
assert ![1, 2, 3].any { it > 3 }

assert [1, 2, 3, 4, 5, 6].sum() == 21                // 使用plus()求和
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                     // reduce操作
} == 'counting: 123'
assert [1, 2, 3].inject(0) { count, item ->
    count + item
} == 6

这是用于查找集合中的最大值和最小值的惯用 Groovy 代码:

def list = [9, 4, 2, 10, 5]
assert list.max() == 10
assert list.min() == 2

// 我们也可以比较单个字符,就像任何可比较的字符一样
assert ['x', 'y', 'a', 'z'].min() == 'a'

// 我们可以使用闭包来指定排序行为
def list2 = ['abc', 'z', 'xyzuvw', 'Hello', '321']
assert list2.max { it.size() } == 'xyzuvw'
assert list2.min { it.size() } == 'z'

除了闭包,您还可以使用 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

Comparator mc2 = { a, b -> a == b ? 0 : (Math.abs(a) < Math.abs(b)) ? -1 : 1 }


assert list.max(mc2) == -13
assert list.min(mc2) == -1

assert list.max { a, b -> a.equals(b) ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } == -13
assert list.min { a, b -> a.equals(b) ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } == -1

4.2.添加和删除

我们可以使用[]分配一个新的空列表,并使用<<向其添加项目:

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']]

// << 链中的第一项是目标列表
assert ([1, 2] << 3 << [4, 5] << 6) == [1, 2, 3, [4, 5], 6]

// 使用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]

def a = [1, 2, 3]
a += 4      // 创建一个新列表并将其分配给`a`
a += [5, 6]
assert a == [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 = [1, 2]
list.add(1, 3) // 在索引`1`之前添加`3`
assert list == [1, 3, 2]

list.addAll(2, [5, 4]) // 在索引`2`之前添加`[5,4]`
assert list == [1, 3, 5, 4, 2]

list = ['a', 'b', 'z', 'e', 'u', 'v', 'g']
list[8] = 'x' // []运算符正在根据需要增加列表
// 如果需要,插入null
assert list == ['a', 'b', 'z', 'e', 'u', 'v', 'g', null, 'x']

然而,重要的是,列表上的+运算符没有变异。与<<相比,它将创建一个新的列表,这通常不是您想要的,并且可能会导致性能问题。

Groovy 开发工具包还包含允许您轻松地按值从列表中删除元素的方法:

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           // 通过从原始列表中删除`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']
assert list.remove(2) == 'c'        // 删除第三个元素,并返回它
assert list == ['a','b','d','e','f','b','b','a']

如果您只想删除列表中具有相同值的第一个元素,而不是删除所有元素,您可以调用remove传递值的方法:

def list= ['a','b','c','b','b']
assert list.remove('c')             // 删除 'c', 并返回 true 因为元素被删除了
assert list.remove('b')             // 删除第一个 'b', 并返回 true 因为元素被删除了

assert ! list.remove('z')           // 返回 false 因为没有元素被删除
assert list == ['a','b','b']

如您所见,有两种remove方法可用。一个接受整数并按其索引删除元素,另一个将删除与传递的值匹配的第一个元素。那么当我们有一个整数列表时我们应该怎么做呢?在这种情况下,您可能希望使用removeAt按索引删除元素,并removeElement删除与值匹配的第一个元素。

def list = [1,2,3,4,5,6,2,2,1]

assert list.remove(2) == 3          // 删除第三个元素,并返回它
assert list == [1,2,4,5,6,2,2,1]

assert list.removeElement(2)        // 删除第一个 2 并返回 true
assert list == [1,4,5,6,2,2,1]

assert ! list.removeElement(8)      // 返回 false 因为 8 不存在
assert list == [1,4,5,6,2,2,1]

assert list.removeAt(1) == 4        // 删除索引为 1 的元素, 并返回它
assert list == [1,5,6,2,2,1]

当然,removeAtremoveElement适用于任何类型的列表。
此外,可以通过调用以下clear方法来删除列表中的所有元素:

def list= ['a',2,'c',4]
list.clear()
assert list == []

4.3.包含和统计

Groovy 开发工具包还包括便于在集合上进行推理的方法:

assert 'a' in ['a','b','c']             // 如果元素属于列表,则返回true
assert ['a','b','c'].contains('a')      // 等价于Java中的`contains`方法
assert [1,3,4].containsAll([1,4])       // `containsAll` 将检查是否找到所有元素

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] )

4.4.排序

使用集合通常意味着排序。Groovy 提供了多种列表排序选项,从使用闭包到比较器,如以下示例所示:

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]

4.5.复制元素

Groovy 开发工具包还利用运算符重载来提供允许重复列表元素的方法:

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]