Groovy 宇宙飞船运算符
最后修改于 2025 年 3 月 20 日
Groovy 中的宇宙飞船运算符 <=> 简化了比较,根据左操作数是否小于、等于或大于右操作数,返回 -1、0 或 1。它非常适合排序和自定义比较,提高了可读性,优于传统方法。本教程将通过示例探讨其用法。
数值比较
宇宙飞船运算符比较两个值,产生一个整数结果,指示它们的相对顺序,使其直观易懂,适合基本检查。
def a = 5 def b = 8 println a <=> b // Output: -1 println b <=> a // Output: 1 println a <=> a // Output: 0
a <=> b 比较 5 和 8:5 < 8,所以结果是 -1。b <=> a 给出 1 (8 > 5),而 a <=> a 是 0 (5 = 5)。这些结果模仿了 Java 的 compareTo,但运算符的语法更简洁且视觉上更清晰。
按长度对字符串进行排序
宇宙飞船运算符在排序方面表现出色,尤其是在闭包中,它允许根据属性对字符串列表等集合进行自定义排序。
def words = ['sky', 'water', 'emotion', 'shredder',
'anonymous', 'on', 'a', 'copper', 'the', 'elephant']
words.sort { e1, e2 -> e1.length() <=> e2.length() }
println words
words.sort { e1, e2 -> e2.length() <=> e1.length() }
println words
e1.length() <=> e2.length() 按字符串长度升序排序 words:从 "a" (1) 到 "anonymous" (9)。通过 e2.length() <=> e1.length() 反向排序,则按降序排序:从 "anonymous" 到 "a"。运算符的输出 (-1, 0, 1) 控制排序顺序,展示了其在自定义比较中的强大功能。
$ groovy SortByLength.groovy [a, on, sky, the, water, copper, emotion, shredder, elephant, anonymous] [anonymous, elephant, shredder, emotion, copper, water, the, sky, on, a]
排序自定义对象
通过宇宙飞船运算符实现 Comparable 接口,可以对自定义对象进行排序,以自然、可重用的方式比较它们的属性。
class User implements Comparable {
String fname
String lname
String occupation
User(String fname, String lname, String occupation) {
this.fname = fname
this.lname = lname
this.occupation = occupation
}
int compareTo(o) {
this.lname <=> o.lname
}
String toString() {
"${fname} ${lname} - ${occupation}"
}
}
def users = [
new User('John', 'Doe', 'gardener'),
new User('Roger', 'Roe', 'driver'),
new User('Lucia', 'Smith', 'accountant'),
new User('Paul', 'Newman', 'firefighter'),
new User('Adam', 'Clapton', 'teacher'),
new User('Jane', 'Walter', 'pilot')
]
println users
println users.sort()
User 类在 compareTo 方法中使用 this.lname <=> o.lname 来按姓氏排序。sort() 方法按字母顺序对 users 进行排序:从 "Clapton" 到 "Walter"。宇宙飞船运算符按字典顺序比较字符串,与 Groovy 的自定义对象排序方法无缝集成。
$ groovy SortUsers.groovy [John Doe - gardener, Roger Roe - driver, Lucia Smith - accountant, Paul Newman - firefighter, Adam Clapton - teacher, Jane Walter - pilot] [Adam Clapton - teacher, John Doe - gardener, Paul Newman - firefighter, Roger Roe - driver, Lucia Smith - accountant, Jane Walter - pilot]
比较混合类型
宇宙飞船运算符可以优雅地处理混合类型,根据需要转换操作数,这使其对于异构数据比较非常通用。
def values = [5, "10", 3.14, "2"]
values.sort { a, b -> a <=> b }
println values
a <=> b 对混合类型(整数、字符串、浮点数)的 values 进行排序。Groovy 在可能的情况下将字符串强制转换为数字,结果为 [3.14, "2", 5, "10"]。数字比较优先,显示了该运算符在处理类型多样性方面的灵活性。
$ groovy MixedTypes.groovy [3.14, 2, 5, 10]
使用宇宙飞船进行过滤
除了排序,宇宙飞船运算符还可以通过与阈值进行比较来过滤集合,利用其在条件逻辑中的数值输出。
def numbers = [15, 7, 22, 3, 19, 10]
def threshold = 12
def above = numbers.findAll { it <=> threshold > 0 }
println above
it <=> threshold > 0 查找大于 12 的数字。如果 it <=> threshold 的结果是 1 (it > 12),则该数字被包含在内,结果为 [15, 22, 19]。这直接在过滤器中使用运算符的结果,将其用途从排序扩展到选择任务。
$ groovy FilterSpaceship.groovy [15, 22, 19]
自定义多属性排序
宇宙飞船运算符可以链接比较来进行多标准排序,在主要标准相同时比较次要属性,从而提供精细的控制。
class Product {
String name
int price
Product(String name, int price) {
this.name = name
this.price = price
}
String toString() { "${name} (\$${price})" }
}
def products = [
new Product("Laptop", 1200),
new Product("Mouse", 25),
new Product("Laptop", 800),
new Product("Keyboard", 50)
]
products.sort { a, b ->
def nameCmp = a.name <=> b.name
nameCmp != 0 ? nameCmp : a.price <=> b.price
}
println products
a.name <=> b.name 首先按名称排序。如果名称相等(0),则 a.price <=> b.price 来打破平局。 "Laptop" 按价格 (800, 1200) 排序,然后是 "Keyboard" 和 "Mouse"。这演示了运算符的链接能力在分层排序中的应用。
$ groovy MultiSort.groovy [Laptop ($800), Laptop ($1200), Keyboard ($50), Mouse ($25)]
宇宙飞船在条件逻辑中的应用
运算符的 -1、0、1 输出可以驱动 if-else 逻辑,提供一种紧凑的方式来对值之间的关系进行分类,而无需进行多次比较。
def x = 7
def y = 10
def result = (x <=> y) switch {
-1 -> "less than"
0 -> "equal to"
1 -> "greater than"
}
println "$x is $result $y" // Output: 7 is less than 10
x <=> y (7 < 10) 返回 -1,通过 switch 映射为 "小于"。这避免了单独的 <、==、> 检查,使用运算符的结果简洁地描述了 x 和 y 之间的关系。
来源
本教程涵盖了 Groovy 宇宙飞船运算符 <=>,展示了其在排序、过滤和自定义比较中的应用,并附带实际示例。
作者
列出 所有 Groovy 教程。