Groovy 数组
最后修改于 2025 年 3 月 20 日
Groovy 中的数组是固定大小的集合,用于存储相同类型的元素。与列表不同,数组在创建后其大小无法更改。本教程将深入介绍如何创建数组、操作数组以及执行诸如排序、过滤和映射等常见任务,并附带实际示例指导您完成整个过程。
列表 vs 数组
在 Groovy 中,列表和数组在初始化时看起来可能相似,但它们是不同的。列表是动态的,可以增长或缩小,而数组的大小是固定的。由于它们的语法相似,您必须使用 as
或类型注解显式声明一个数组,以避免默认创建列表。
def nums = [1, 2, 3, 4, 5] println nums.class.name def nums2 = [1, 2, 3, 4, 5] as int[] println nums2.class.name
如果没有 as int[]
,nums
默认是一个 java.util.ArrayList
,一种列表类型。通过添加 as int[]
,nums2
成了一个整数数组。您可以在右侧使用 as
或在左侧使用类型声明来指定数组类型,这为您定义数组提供了灵活性。
$ groovy ListVsArray.groovy java.util.ArrayList int[]
数组创建
Groovy 利用其简洁的语法提供了多种创建数组的方法。您可以使用 as
关键字和类列表初始化器,或者使用 new
关键字和显式类型及值。这两种方法都很直接,并且根据您的偏好常用。
def vals = [1, 2, 3, 4, 5] as int[] println vals println vals.length println vals.size() def words = new String[] {'sky', 'cloud', 'pen'} println words
在这里,vals
是使用 as int[]
创建的,而 words
使用 new String[]
语法。length
和 size
都返回元素的数量,提供了检查数组长度的两种方法。这种双重性源于 Groovy 对 Java 兼容性的融合及其自身的增强。
$ groovy ArrayCreation.groovy [1, 2, 3, 4, 5] 5 5 [sky, cloud, pen]
通过范围创建数组
Groovy 的范围运算符 (..
) 提供了一种快速而优雅的方式来定义具有顺序值的数组。这在您想要连续序列而无需手动列出每个元素时,对于数字数组尤其有用。
int[] nums = -3..2 println nums
表达式 -3..2
生成一个从 -3 到 2(包括两端)的数组,共包含六个元素。这种简写是 Groovy 中的一个强大功能,它简化了数字范围的数组创建,并使您的代码更具可读性和简洁性。
$ groovy RangeArray.groovy [-3, -2, -1, 0, 1, 2]
数组操作
Groovy 数组附带内置方法来执行常见操作,如查找大小、最小值、最大值、总和、平均值以及计数。这些方法使数组在数据操作方面具有通用性,无需复杂的循环或外部库。
int[] nums = -4..10 println nums.size() println nums.min() println nums.max() println nums.sum() println nums.average() println nums.count(-4) String[] words = ['sky', 'waterfall', 'superintendent', 'war'] println words.max { it.size() } println words.min { it.size() }
对于数字,size
获取长度,min
和 max
查找极值,sum
添加所有元素,average
计算平均值,count(-4)
计算 -4 的出现次数。对于字符串,max
和 min
可以使用闭包,如 { it.size() }
,根据长度进行比较,这展示了 Groovy 在自定义标准方面的灵活性。
$ groovy ArrayOps.groovy 15 -4 10 45 3.0 1 superintendent sky
元素访问
您可以使用方括号运算符 ([]
) 或 getAt
方法来访问数组元素,这两种方式都支持正索引、负索引和范围。这提供了多种检索单个元素或数组切片的方法。
int[] nums = -3..2 println nums[0] println nums[1] println nums.getAt(0) println nums.getAt(-1) println nums[-1..1] String[] words = ['borrow', 'water', 'globe'] println words[0..2]
索引 0 获取第一个元素,而 -1 获取最后一个元素。范围 -1..1
从末尾向开头提取一个子数组,而 0..2
获取前三个元素。负索引是 Groovy 的一个便利功能,它从末尾开始倒数,使得在不手动计算偏移量的情况下处理数组更加容易。
$ groovy ElementAccess.groovy -3 -2 -3 2 [2, 1, 0, -1] [borrow, water, globe]
迭代
在 Groovy 中,可以使用传统的 for
循环或更具惯用性的 each
方法(支持闭包)来迭代数组。这些选项迎合了不同的编码风格,并提供了额外的功能,如索引跟踪。
def nums = [1, 2, 3, 4, 5] as int[] for (def e in nums) { println e } def words = ['sky', 'blue', 'war'] as String[] words.each { println it } words.eachWithIndex { e, i -> println "${i}: ${e}" }
for
循环迭代 nums
中的每个元素,每行打印一个。each
方法使用闭包对 words
执行相同的操作,其中 it
是默认参数。eachWithIndex
添加了索引 (i
),让您可以跟踪位置,这对于带编号的输出或顺序很重要时很有用。
$ groovy Iteration.groovy 1 2 3 4 5 sky blue war 0: sky 1: blue 2: war
检查元素是否存在
contains
方法用于检查特定元素是否存在于数组中,并返回一个布尔值。这是一种无需编写循环或复杂逻辑即可测试成员资格的简单方法。
String[] words = ['sky', 'water', 'war', 'pen'] println words.contains('war') println words.contains('small')
contains('war')
返回 true
,因为 "war" 存在于数组中,而 contains('small')
返回 false
,因为 "small" 不存在。此方法区分大小写且完全匹配,使其对于直接检查非常可靠。
$ groovy Contains.groovy true false
修改数组
Groovy 数组的大小是固定的,因此您无法直接删除元素,但可以使用 -
运算符修改它们或创建不包含某些元素的新数组。这反映了数组的固定长度,同时仍然允许灵活性。
String[] words = ['sky', 'water', 'war', 'cup'] def words2 = words - 'war' println words println words2 words[0] = 'skylark' println words
-
运算符不会改变 words
,但会返回一个不包含 "war" 的新数组 words2
。原始数组保持不变,显示了其固定大小的不可变性。将 words[0] = 'skylark'
赋值会替换一个元素,证明您可以在固定结构内更新值,但不能改变长度。
$ groovy ModifyArray.groovy [sky, water, war, cup] [sky, water, cup] [skylark, water, war, cup]
打乱元素
shuffle
方法会就地随机化数组中元素的顺序,这意味着它会直接修改原始数组。这对于随机抽样或测试不同序列等任务很有用。
String[] words = ['sky', 'cloud', 'pen'] println words words.shuffle() println words words.shuffle() println words
每次调用 shuffle
都会随机重排 words
。由于它是就地操作,每次都会修改原始数组,并且每次运行的输出都不同。这表明 Groovy 能够提供强大的、可变的数组操作,尽管它们的大小是固定的。
$ groovy ShuffleArray.groovy [sky, cloud, pen] [cloud, pen, sky] [pen, sky, cloud]
排序
sort
方法会就地将数组元素按升序排列,修改原始数组。与 reverse
结合使用,它可以控制排序方向,使数组易于组织。
String[] words = ['sky', 'water', 'war', 'pen'] println words.sort() println '----------------------------' println words.reverse()
sort
会将 words
按字母顺序排列,将其从初始顺序更改为 [pen, sky, war, water]。然后,reverse
将其翻转为降序。这两种操作都会直接修改数组,展示了 Groovy 如何将简洁性与直接操作相结合以进行排序任务。
$ groovy SortArray.groovy [pen, sky, war, water] ---------------------------- [water, war, sky, pen]
过滤
grep
方法根据闭包中定义的条件过滤数组,并返回一个只包含匹配元素的新数组。这是一种在不编写显式循环的情况下提取子集的简洁方法。
String[] words = ['sky', 'water', 'war', 'pen'] def res = words.grep { it.startsWith('w') } println res
在这里,grep { it.startsWith('w') }
只保留以 "w" 开头的元素,生成一个包含 "water" 和 "war" 的新数组。原始数组未被更改,并且闭包允许灵活的自定义过滤条件,展示了 Groovy 的函数式编程能力。
$ groovy FilterArray.groovy [water, war]
映射
collect
方法将转换应用于每个元素,并返回一个包含结果的新数组。这是 Groovy 的数据映射方式,可用于根据原始数组转换或计算值。
int[] nums = -4..10 def res = nums.collect { it * it } println res
collect { it * it }
会将 nums
中的每个数字平方,创建一个包含结果的新数组。原始数组保持不变,并且闭包可以包含任何表达式,这使得 collect
成为 Groovy 中数据转换的通用工具。
$ groovy MapArray.groovy [16, 9, 4, 1, 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
查找元素
Groovy 提供了 find
和 findAll
来查找符合条件的元素。find
返回第一个匹配项,而 findAll
返回所有匹配项,两者都使用闭包以实现灵活性。
int[] nums = -4..10 def res = nums.findAll { it % 2 == 0 } println res res = nums.find { it > 0 } println res
findAll { it % 2 == 0 }
将所有偶数收集到一个新数组中,而 find { it > 0 }
返回第一个正数 (1)。这些方法不会修改原始数组,并且是使用自定义逻辑进行搜索或过滤的理想选择,增强了 Groovy 的表达能力。
$ groovy FindArray.groovy [-4, -2, 0, 2, 4, 6, 8, 10] 1
连接元素
join
方法将数组元素合并成一个字符串,使用指定的 separator。这对于创建格式化输出或序列化数据而不进行手动连接非常方便。
String[] words = ['sky', 'water', 'war'] def res = words.join(', ') println res
join(', ')
将 words
合并成一个逗号分隔的字符串。分隔符可以是任何字符串,提供了灵活性——使用 "" 表示没有分隔符,或使用类似 " - " 的内容表示其他样式。这是将数组转换为可读文本的简单而强大的方法。
$ groovy JoinArray.groovy sky, water, war
Any 和 Every
any
和 every
方法测试数组元素满足的条件,并返回布尔值。any
检查是否至少有一个元素满足条件,而 every
检查是否所有元素都满足条件,两者都使用闭包。
int[] nums = -4..10 println nums.any { it > 0 } println nums.every { it > 0 }
any { it > 0 }
返回 true
,因为有些数字是正数,而 every { it > 0 }
返回 false
,因为有些数字是负数或零。这些方法对于在不手动迭代的情况下验证数组的属性非常高效。
$ groovy AnyEveryArray.groovy true false
展平数组
flatten
方法接受一个嵌套数组(数组的数组),并将其转换为一个单一的、扁平的数组。在处理多维数据并希望将其作为单个序列进行处理时,这非常有用。
int[][] nums = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] println nums println nums.flatten()
nums
开始时是一个 3x3 的数组,而 flatten
将其转换为一个包含九个元素的单个数组。原始结构在展平之前被保留,结果是一个新数组,nums
保持不变,除非被重新赋值。这简化了对嵌套数据的处理。
$ groovy FlattenArray.groovy [[1, 2, 3], [4, 5, 6], [7, 8, 9]] [1, 2, 3, 4, 5, 6, 7, 8, 9]
来源
本教程通过实际示例探讨了 Groovy 数组。
作者
列出 所有 Groovy 教程。