Contents

Groovy中列表

1. 概述

Groovy 中,我们可以像在Java 中一样使用列表。但是,由于它对扩展方法的支持,它附带了更多。

在本教程中,我们将了解 Groovy 对列表的变异、过滤和排序的看法。

2. 创建 Groovy 列表

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 使用“==”运算符来比较两个列表中的元素是否相等。继续前面的示例,将cloneListarrlist进行比较,结果为true

assertTrue(cloneList == arrList)

现在,让我们看看如何对列表进行一些常见的操作。

3. 从列表中检索项目

我们可以使用文字语法从列表中获取项目,例如:

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

或使用*get()getAt()*方法:

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

我们还可以使用正索引和负索引从列表中获取项目。当使用负索引时,列表从右到左读取:

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

最后,我们可以使用“ += ”运算符将新项目添加到列表中。与其他方法相比,此运算符创建一个新的列表对象并将其分配给变量list

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

在此示例中,索引 1 和 2 处的项目将更新为新值。

6. 从列表中删除项目

我们可以使用*remove()*方法删除特定索引处的项目:

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()*方法删除一个元素。这会从列表中删除第一次出现的元素:

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 传递一个隐式参数it对应于每次迭代中的当前元素:

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

让我们看另一个例子。在这里,我们想要一个包含所有数字元素的列表:

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

或者,我们可以使用grep方法来做同样的事情:

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

grepfind方法的区别在于grep可以接受ObjectClosure作为参数。**因此,它允许进一步将条件语句减少到最低限度:

assertTrue(filterList.grep {it > 6} == [76])

此外,grep使用*Object#isCase(java.lang.Object)*来评估列表中每个元素的条件。

有时我们可能只对列表中的唯一项目感兴趣。为此,我们可以使用两种重载方法。

*unique()*方法可选地接受一个闭包,并在底层列表中只保留与闭包条件匹配的元素,同时丢弃其他元素。它默认使用自然排序来确定唯一性:

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

或者,如果要求不改变底层列表,那么我们可以使用*toUnique()*方法:

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

*如果我们想检查列表中的某些或所有项目是否满足某个条件,我们可以使用*every()any()方法。

every()方法根据列表中的每个元素评估闭包中的条件。然后,仅当列表中的所有元素都满足条件时才返回true

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

另一方面,如果列表中的任何元素满足条件,则any()方法返回true

assertTrue(conditionList.any {it % 2 == 0})

9. 排序

默认情况下,Groovy 根据自然顺序对列表中的项目进行排序:

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

此外,我们可以使用min()max()方法来查找最大值或最小值,而无需显式调用sort()

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