1. 简介

Groovy 中,我们处理列表的方式和 Java 类似,但由于其支持扩展方法(extension methods),Groovy 提供了更加丰富的 API 来操作集合。

本文将重点介绍 Groovy 在列表的增删改查、迭代、过滤、排序等方面的特性。

2. 创建 List

Groovy 提供了一些便捷语法来创建列表,这得益于其动态类型和字面量语法的支持。

我们可以通过简写方式创建一个包含元素的列表:

def list = [1,2,3]

也可以创建一个空列表:

def emptyList = []

默认情况下,Groovy 创建的是 java.util.ArrayList 的实例。

我们可以显式指定列表类型:

def linkedList = [1,2,3] as LinkedList
ArrayList arrList = [1,2,3]

还可以使用构造函数从已有列表创建新列表:

def copyList = new ArrayList(arrList)

或者通过克隆:

def cloneList = arrList.clone()

⚠️ 注意:克隆是浅拷贝。

Groovy 使用 == 运算符比较两个列表的内容是否相等。例如:

assertTrue(cloneList == arrList)

3. 获取列表元素

我们可以使用下标语法获取列表中的元素:

def list = ["Hello", "World"]
assertTrue(list[1] == "World")

也可以使用 get()getAt() 方法:

assertTrue(list.get(1) == "World")
assertTrue(list.getAt(1) == "World")

Groovy 支持负数索引,表示从右往左读取:

assertTrue(list[-1] == "World")
assertTrue(list.getAt(-2) == "Hello")

⚠️ 注意:get() 方法不支持负索引。

4. 向列表添加元素

有多种方式可以向列表中添加元素。

先定义一个空列表并添加几个元素:

def list = []

list << 1
list.add("Apple")
assertTrue(list == [1, "Apple"])

我们也可以指定索引插入元素:

⚠️ 如果指定的索引大于当前列表长度,Groovy 会自动填充 null

list[2] = "Box"
list[4] = true
assertTrue(list == [1, "Apple", "Box", null, true])

还可以使用 += 操作符:

⚠️ 与上面不同的是,这个操作符会生成一个新的列表对象:

def list2 = [1,2]
list += list2
list += 12        
assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12])

5. 更新列表元素

可以使用下标或 set() 方法更新列表中的元素:

def list =[1, "Apple", 80, "App"]
list[1] = "Box"
list.set(2,90)
assertTrue(list == [1, "Box", 90,  "App"])

6. 删除列表元素

使用 remove(index) 可以删除指定索引位置的元素:

def list = [1,2,3,4,5,5,6,6,7]
list.remove(3)
assertTrue(list == [1,2,3,5,5,6,6,7])

使用 removeElement(element) 删除第一个匹配的元素:

list.removeElement(5)
assertTrue(list == [1,2,3,5,6,6,7])

⚠️ 使用 - 操作符可以删除所有匹配的元素,且不会修改原列表,而是返回新列表:

assertTrue(list - 6 == [1,2,3,5,7])

7. 遍历列表

Groovy 扩展了 Java 的 Collections API,提供了更简洁的遍历方法。

each()

类似 Java 的 forEach,Groovy 的 each 方法接受一个闭包:

def list = [1,"App",3,4]
list.each {println it * 2}

eachWithIndex()

除了元素本身,还提供当前索引:

list.eachWithIndex{ it, i -> println "$i : $it" }

8. 过滤操作

Groovy 提供了多种方法来过滤列表。

先定义一个测试列表:

def filterList = [2,1,3,4,5,6,76]

find()

返回第一个满足条件的元素:

assertTrue(filterList.find {it > 3} == 4)

findAll()

返回所有满足条件的元素组成的列表:

assertTrue(filterList.findAll {it > 3} == [4,5,6,76])

grep()

功能类似于 findAll,但支持传入类型或闭包:

assertTrue(filterList.grep( Number ) == [2,1,3,4,5,6,76])
assertTrue(filterList.grep {it > 6} == [76])

unique() 和 toUnique()

获取唯一元素:

def uniqueList = [1,3,3,4]
uniqueList.unique()
assertTrue(uniqueList == [1,3,4])

不修改原列表:

assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique {it.size()} == ["A", "Ba", "Bat"])

every() 和 any()

判断是否所有或任一元素满足条件:

def conditionList = [2,1,3,4,5,6,76]
assertFalse(conditionList.every {it < 6})
assertTrue(conditionList.any {it % 2 == 0})

9. 排序操作

默认使用自然排序:

assertTrue([1,2,1,0].sort() == [0,1,1,2])

也可以传入自定义 Comparator

Comparator mc = {a,b -> a == b? 0: a < b? 1 : -1}
def list = [1,2,1,0]
list.sort(mc)
assertTrue(list == [2,1,1,0])

max() 和 min()

直接获取最大或最小值:

def strList = ["na", "ppp", "as"]
assertTrue(strList.max() == "ppp")
Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1}
def numberList = [3, 2, 0, 7]
assertTrue(numberList.min(minc) == 0)

10. 映射(Collect)

使用 collect 可以将列表元素转换后生成新列表:

def list = ["Kay","Henry","Justin","Tom"]
assertTrue(list.collect{"Hi " + it} == ["Hi Kay","Hi Henry","Hi Justin","Hi Tom"])

11. 拼接(Join)

使用 join 可以将列表拼接为字符串:

assertTrue(["One","Two","Three"].join(",") == "One,Two,Three")

12. 总结

本文介绍了 Groovy 对 Java Collections API 的扩展,包括:

  • 列表的创建、增删改查
  • 遍历、过滤、排序、去重、映射等操作

Groovy 的这些扩展极大地简化了集合操作,让代码更简洁、更易读。如果你是经验丰富的 Java 开发者,这些特性会让你写 Groovy 时如鱼得水。✅


原始标题:Lists in Groovy | Baeldung