Groovy Switch 表达式
最后修改于 2025 年 3 月 20 日
Groovy 中的 Switch 表达式,也称为模式匹配,提供了一种处理多个条件的简洁方式。与传统 switch 不同,它们返回一个值,增强了表达力。本教程通过示例探讨了它们的通用性。
简单 Switch
Switch 表达式使用 `->` 语法根据条件返回值,简化了基本的决策制定。
def num = 3 def res = switch (num) { case 3 -> "three" default -> "other" } println res
switch (num)
检查 num
(3) 与 case。case 3
匹配,返回 "three"。default
case 处理不匹配的值。这种紧凑的形式直接返回值,不像基于语句的 switch。
$ groovy SimpleSwitch.groovy three
匹配字符串字面量
Switch 表达式可以匹配字符串输入,使其成为基于文本的条件的理想选择,例如用户响应。
def res = System.console().readLine 'Capital of Slovakia?: ' def capital = res.capitalize() def msg = switch (capital) { case 'Bratislava' -> 'correct answer' default -> 'wrong answer' } println msg
readLine
获取用户输入,并将其大写以保持一致。switch (capital)
检查是否为 "Bratislava",返回 "correct answer",否则通过 default
返回 "wrong answer"。这展示了带回退机制的字符串匹配,对于测验或验证很有用。
$ groovy SwitchStrings.groovy Capital of Slovakia?: bratislava correct answer
匹配整数
整数匹配允许 switch 表达式处理数字选项,这在菜单驱动的程序中很常见。
def menu = ''' Select option 1 - start 2 - slow down 3 - accelerate 4 - pause 5 - terminate ''' println menu def opt = System.console().readLine ': ' def res = switch (opt as Integer) { case 1 -> 'start' case 2 -> 'slow down' case 3 -> 'accelerate' case 4 -> 'pause' case 5 -> 'terminate' default -> 'unknown' } println "your option: $res"
显示菜单,然后 opt as Integer
将输入转换为数字。switch
将 1-5 映射到操作,default
用于无效输入。这将返回一个字符串,如 "your option: accelerate",演示了数字模式匹配。
$ groovy SwitchIntegers.groovy Select option 1 - start 2 - slow down 3 - accelerate 4 - pause 5 - terminate : 3 your option: accelerate
匹配类型
Switch 表达式可以匹配对象类型,在混合集合中识别值的类。
def data = [1, 2.2, 'falcon', true, [1, 2, 3], 2g] for (e in data) { def res = switch (e) { case Integer -> 'integer' case String -> 'string' case Boolean -> 'boolean' case List -> 'list' default -> 'other' } println res }
data
包含各种类型。switch (e)
检查每个元素的类型,返回一个标签(例如,1 为 "integer",[1, 2, 3] 为 "list")。default
捕获 BigDecimal (2g)。这突显了用于动态数据的基于类型的模式匹配。
$ groovy SwitchTypes.groovy integer other string boolean list other
多个选项
逗号分隔的 case 将多个值分组到一个结果下,从而简化了具有共享结果的条件。
def grades = ['A', 'B', 'C', 'D', 'E', 'F', 'FX'] for (grade in grades) { switch (grade) { case 'A' , 'B' , 'C' , 'D' , 'E' , 'F' -> println('passed') case 'FX' -> println('failed') } }
grades
列出了成绩。case 'A' , 'B' , ...
对及格成绩 (A-F) 进行分组,打印 "passed",而 'FX' 打印 "failed"。这种逗号语法将多个匹配合并为一个操作,提高了可读性。
$ groovy SwitchMultiple.groovy passed passed passed passed passed passed failed
默认选项
递归函数中的 default
case 提供了一个通配符,演示了 switch 表达式的返回值实用性。
def factorial(n) { switch (n) { case 0, 1 -> 1 default -> n * factorial(n - 1) } } for (i in 0g..5g) { def f = factorial(i) println("$i $f") }
factorial
使用 switch
计算阶乘。case 0, 1
返回 1(基本情况),default
递归乘法。循环打印从 0 到 5 的阶乘(例如,5 120)。这表明 switch 在递归中作为表达式。
$ groovy SwitchDefault.groovy 0 1 1 1 2 2 3 6 4 24 5 120
选项内的 Guard
Guard 使用闭包为 case 添加条件,从而超越简单的相等性来细化匹配。
def rnd = new Random() def ri = rnd.nextInt(-5, 5) def res = switch (ri) { case { ri < 0 } -> "${ri}: negative value" case { ri == 0 } -> "${ri}: zero" case { ri > 0 } -> "${ri}: positive value" } println res
ri
是一个随机整数(-5 到 4)。switch
使用 guard:{ ri < 0 }
用于负数,{ ri == 0 }
用于零,{ ri > 0 }
用于正数。输出各不相同(例如,“-3: negative value”),展示了动态条件匹配。
$ groovy SwitchGuards.groovy 2: positive value // varies per run
匹配枚举
Enum 与 switch 表达式自然配对,匹配特定常量以实现类型安全逻辑。
enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } def days = [Day.Monday, Day.Tuesday, Day.Wednesday, Day.Thursday, Day.Friday, Day.Saturday, Day.Sunday] def res = [] def random = new Random() (0..3).each { res << days[random.nextInt(days.size())] } for (e in res) { switch (e) { case Day.Monday -> println("monday") case Day.Tuesday -> println("tuesday") case Day.Wednesday -> println("wednesday") case Day.Thursday -> println("thursday") case Day.Friday -> println("friday") case Day.Saturday -> println("saturday") case Day.Sunday -> println("sunday") } }
Day
enum 定义了工作日。选择四个随机日期,然后 switch
匹配每个日期,打印其名称(例如,“tuesday”)。输出各不相同,但这表明 enum 是 switch 的目标,利用其固定值来实现清晰度。
$ groovy SwitchEnums.groovy friday monday sunday thursday // varies per run
匹配 Enum 范围
Switch 表达式支持 enum 范围,将连续值分组以实现简洁的逻辑。
enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } def isWeekend(Day d) { switch (d) { case Day.Monday..Day.Friday -> false case Day.Saturday, Day.Sunday -> true } } def days = [Day.Monday, Day.Tuesday, Day.Wednesday, Day.Thursday, Day.Friday, Day.Saturday, Day.Sunday] for (e in days) { if (isWeekend(e)) { println('weekend') } else { println('weekday') } }
isWeekend
使用 Monday..Friday
用于工作日(false)和 Saturday, Sunday
用于周末(true)。循环测试所有日期,打印五次“weekday”,然后两次“weekend”。这有效地结合了范围和多个匹配。
$ groovy SwitchEnumRanges.groovy weekday weekday weekday weekday weekday weekend weekend
匹配对象
Switch 表达式可以匹配对象类型,将相关类分组以进行共享处理。
record Cat(String name) {} record Dog(String name) {} record Person(String name) {} def data = [new Cat('Missy'), new Dog('Jasper'), new Dog('Ace'), new Person('Peter'), 'Jupiter'] for (e in data) { switch (e) { case Cat, Dog -> println("${e} is a pet") case Person -> println("${e} is a human") default -> println('unknown') } }
Cat
、Dog
和 Person
是记录。case Cat, Dog
对宠物进行分组,case Person
匹配人类,default
捕获其他(例如,“Jupiter”)。这会打印基于类型的消息,显示对象模式匹配。
$ groovy SwitchObjects.groovy Cat[name=Missy] is a pet Dog[name=Jasper] is a pet Dog[name=Ace] is a pet Person[name=Peter] is a human unknown
匹配范围
Switch 表达式中的数字范围检查一个值是否在边界内,这对于对数字进行分类很有用。
def rnd = new Random() def ri = rnd.nextInt(0, 120) switch (ri) { case 1..30 -> println('value is in 1 to 30') case 31..60 -> println('value is in 31 to 60') case 61..90 -> println('value is in 61 to 90') case 91..120 -> println('value is in 91 to 120') }
ri
是随机的(0-119)。switch
检查范围(例如,1..30
),打印匹配范围的消息。输出各不相同(例如,“value is in 61 to 90”),展示了范围如何有效地划分数值。
$ groovy SwitchRanges.groovy value is in 61 to 90 // varies per run
匹配正则表达式
Switch 表达式可以将字符串与正则表达式模式匹配,根据复杂标准进行过滤。
def words = ['week', 'bitcoin', 'cloud', 'copper', 'raw', 'war', 'cup', 'water'] def selected = [] for (word in words) { def res = switch (word) { case ~/^w.*/ -> word case ~/^c.*/ -> word default -> 'skip' } if (res != 'skip') { selected.add(res) } } println selected
~/^w.*/
匹配以 "w" 开头的单词,~/^c.*/
匹配以 "c" 开头的单词。返回匹配的单词,其他则为 "skip"。selected
收集匹配项(例如,“week”、“cloud”),显示了正则表达式模式匹配的实际应用。
$ groovy SwitchRegex.groovy [week, cloud, copper, war, cup, water]
匹配列表(包含)
Switch 表达式可以检查一个值是否在一个列表中,这对于数据结构中的成员资格测试很有用。
def users = [ ['John', 'Doe', 'gardener'], ['Jane', 'Doe', 'teacher'], ['Roger', 'Roe', 'driver'], ['Martin', 'Molnar', 'programmer'], ['Robert', 'Kovac', 'shopkeeper'], ['Tomas', 'Novy', 'programmer'] ] def occupation = 'programmer' for (user in users) { switch (occupation) { case user -> println("${user[0]} ${user[1]} is a programmer") default -> println("${user[0]} ${user[1]} is not a programmer") } }
users
列出了姓名-职业对。case user
检查 "programmer" 是否在 user
(列表)中,并相应地打印。这识别了程序员(Martin、Tomas),使用列表包含作为模式。
$ groovy SwitchListContains.groovy John Doe is not a programmer Jane Doe is not a programmer Roger Roe is not a programmer Martin Molnar is a programmer Robert Kovac is not a programmer Tomas Novy is a programmer
匹配列表(属性检查)
Switch 表达式可以测试列表属性,例如检查子列表中的值,从而增强数据查询。
def users = [ ['name': 'Paul', 'grades': ['D', 'A', 'B', 'A']], ['name': 'Martin', 'grades': ['F', 'B', 'E', 'FX']], ['name': 'Lucia', 'grades': ['A', 'A', 'B', 'FX']], ['name': 'Jan', 'grades': ['A', 'B', 'B', 'B']] ] for (user in users) { switch ('FX') { case user.grades -> println("${user.name} did not pass") } }
users
将姓名映射到成绩。case user.grades
检查 'FX' 是否在 grades
列表中,并为不及格者(Martin、Lucia)打印。这使用 switch 查询子列表内容,并隐式跳过不匹配项。
$ groovy SwitchListProperty.groovy Martin did not pass Lucia did not pass
来源
本教程通过示例探讨了 Groovy switch 表达式。
作者
列出 所有 Groovy 教程。