Scala 中的模式匹配类似于Java 中的 switch 语法:下面是java中switch代码:
int i = 10
switch (i) {
case 10 :
System.out.println("10");
break;
case 20 :
System.out.println("20");
break;
default :
System.out.println("other number");
break;
}
但是 scala 从语法中补充了更多的功能,所以更加强大。
模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需要匹配时,会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _分支,类似于 Java 中 default 语句。
object Test_PatternMatchBase {
def main(args: Array[String]): Unit = {
// 1. 基本定义语法
val x: Int = 5
val y: String = x match {
case 1 => "one"
case 2 => "two"
case 3 => "three"
case _ => "other"
}
println(y)
// 2. 示例:用模式匹配实现简单二元运算
val a = 25
val b = 13
def matchDualOp(op: Char): Int = op match {
case '+' => a + b
case '-' => a - b
case '*' => a * b
case '/' => a / b
case '%' => a % b
case _ => -1
}
println(matchDualOp('+'))
println(matchDualOp('/'))
println(matchDualOp('\\'))
println("=========================")
// 3. 模式守卫
// 求一个整数的绝对值
def abs(num: Int): Int = {
num match {
case i if i >= 0 => i
case i if i < 0 => -i
}
}
println(abs(67))
println(abs(0))
println(abs(-24))
}
}
Scala 的模式匹配语法类似于 switch 语句,但更加强大和灵活。以下是一些基本的模式匹配示例:
val x: Any = 123
x match {
case i: Int => println("整数:" + i)
case s: String => println("字符串:" + s)
case d: Double => println("双精度浮点数:" + d)
case _ => println("未知类型")
}
在上面的代码中,我们将一个任意类型的值 x
进行了模式匹配。首先,我们使用 case i: Int =>
匹配整数类型并将其赋值给变量 i
,然后执行 println("整数:" + i)
输出整数。接着,我们使用 case s: String =>
匹配字符串类型,并输出对应的信息。最后,我们使用 _
表示其他所有类型并输出 “未知类型”。
除了基本类型之外,模式匹配还支持对列表、元组等复杂类型进行匹配,例如:
def sum(lst: List[Int]) : Int = lst match {
case Nil => 0
case x :: tail => x + sum(tail)
}
println(sum(List(1, 2, 3))) // 输出 6
在上面的代码中,我们定义了一个 sum
函数用于计算列表中所有整数的和。在函数内部,我们使用模式匹配来处理两种情况:当列表为空时(case Nil => 0
),返回 0;否则,我们使用 case x :: tail =>
匹配列表的头部元素 x
和剩余元素 tail
,并递归地调用 sum(tail)
来计算剩余元素的和,并将其与头部元素 x
相加。
需要注意的是,在模式匹配中,每个匹配分支都必须满足类型一致性和互斥性,以避免出现匹配二义性的情况。
object TestMatchGuard {
def main(args: Array[String]): Unit = {
//求一个整数的绝对值
def abs(x: Int) = x match {
case i: Int if i >= 0 => i
case j: Int if j < 0 => -j
case _ => "type illegal"
}
println(abs(-5))
}
}
在 Scala 中,模式匹配非常灵活,可以在各种情况下使用。以下是一些常见的模式匹配运用情况示例:
val x: Any = 123
x match {
case 0 => println("匹配到 0")
case 1 | 2 => println("匹配到 1 或 2")
case i: Int if i > 100 => println("匹配到大于 100 的整数")
case _ => println("未匹配到")
}
val tuple: (String, Int) = ("Scala", 3)
tuple match {
case ("Java", _) => println("第一个元素是 Java")
case (str, num) if num > 0 => println(s"第一个元素是 $str,第二个元素是正整数")
case _ => println("未匹配到")
}
val list: List[Int] = List(1, 2, 3)
list match {
case Nil => println("空列表")
case head :: tail => println(s"头部元素是 $head,剩余元素是 $tail")
}
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
case object UnknownShape extends Shape
val shape: Shape = Circle(3.0)
shape match {
case Circle(r) => println(s"圆形,半径是 $r")
case Rectangle(w, h) => println(s"矩形,宽度是 $w,高度是 $h")
case UnknownShape => println("未知形状")
}
val x: Any = List(1, 2, 3)
x match {
case list: List[_] if list.nonEmpty => println("非空列表")
case list: List[_] if list.isEmpty => println("空列表")
case str: String if str.length > 10 => println("字符串长度大于 10")
case _ => println("未匹配到")
}
在 Scala 中,匹配数组与匹配列表的方式类似。你可以使用模式匹配对数组进行处理。以下是一个示例:
val array: Array[Int] = Array(1, 2, 3)
array match {
case Array() => println("空数组")
case Array(1) => println("单个元素数组")
case Array(1, 2, _*) => println("以1和2开头的数组")
case Array(_, _, 3) => println("以3结尾的数组")
case _ => println("未匹配到")
}
在上面的代码中,我们匹配了不同类型的数组情况。首先,使用 case Array()
匹配空数组;然后,使用 case Array(1)
匹配只包含一个元素的数组;接着,使用 case Array(1, 2, _*)
匹配以 1 和 2 开头的任意长度的数组;最后,使用 case Array(_, _, 3)
匹配以 3 结尾的数组。如果没有匹配到任何情况,就会执行最后一个 case
分支。
需要注意的是,在匹配可变长度的数组时,我们使用了 _*
表示任意长度的数组片段。
在 Scala 中,可以在变量声明中使用模式匹配来提取和赋值变量的值。这种方式被称为模式匹配的变量声明或解构赋值。以下是一个示例:
val tuple: (String, Int) = ("Scala", 3)
val (str, num) = tuple
println(s"字符串:$str")
println(s"整数:$num")
在上面的代码中,我们声明了一个元组 tuple
,包含两个元素:一个字符串和一个整数。然后,我们使用模式匹配的方式将元组中的值解构并赋给了两个新的变量 str
和 num
。这样,我们就可以通过这两个变量来访问元组中的值。
除了元组,还可以在变量声明中匹配其他数据结构,比如列表、数组等。示例如下:
val list: List[String] = List("Hello", "World")
val head :: tail = list
println(s"头部元素:$head")
println(s"剩余元素:$tail")
在上面的代码中,我们声明了一个列表 list
,包含两个字符串元素。然后,使用模式匹配的变量声明方式将列表的头部元素赋给变量 head
,剩余元素赋给变量 tail
。这样,我们就可以分别访问列表的头部元素和剩余元素。
需要注意的是,模式匹配的变量声明在匹配失败时会抛出 MatchError
异常。为了避免这种情况,请确保变量声明与待解构的数据结构具有相同的结构和类型。
在 Scala 中,可以使用模式匹配来匹配各种类型的对象,包括普通类和样例类。其中,样例类是一种特殊的类,它专门用于模式匹配,因为编译器会自动生成带有模式匹配相关方法的代码。以下是一个示例:
sealed trait Fruit
case class Apple(color: String) extends Fruit
case class Banana(length: Int) extends Fruit
case object UnknownFruit extends Fruit
val fruit: Fruit = Apple("red")
fruit match {
case Apple("red") => println("红色苹果")
case Banana(len) if len > 10 => println("长度大于 10 的香蕉")
case UnknownFruit => println("未知水果")
case _ => println("其他水果")
}
在上面的代码中,我们定义了一个 Fruit
样例类及两个子类 Apple
和 Banana
,还有一个对象 UnknownFruit
。然后,我们创建了一个 Apple
对象并将其赋给 fruit
变量。接着,使用 match
关键字来匹配不同类型的 Fruit
对象,分别输出相应的提示信息。
需要注意的是,当匹配样例类时,可以使用模式匹配提取出样例类中的属性值,并对其进行比较。在上面的代码中,使用 case Apple("red")
匹配颜色为红色的苹果。
当数据结构较为复杂时,可以使用嵌套的模式匹配来逐级解构和匹配。
sealed trait Location
case class City(name: String) extends Location
case class Country(name: String, capital: City) extends Location
def printCapital(location: Location): Unit = {
location match {
case Country(_, City(capital)) => println(s"首都是$capital")
case _ => println("未知位置")
}
}
在上面的代码中,我们定义了一个 Location 类及其两个子类 City 和 Country。Country 类包含一个 City 类的实例作为首都。通过嵌套的模式匹配,我们可以提取和打印出国家的首都。