简介
模式匹配是检查某个值(value)是否匹配某一个模式的机制,一个成功的匹配同时会将匹配值解构为其组成部分。它是Java中的switch
语句的升级版,同样可以用于替代一系列的 if/else 语句。
语法
一个模式匹配语句包括一个待匹配的值,match关键字以及至少一个case语句
import scala.util.Random
val x: Int = Random.nextInt(10)
x match{
case 0 => "0"
case 1 => "1"
case 2 => "2"
case _ => "其他" // 使用_代表其他情况
}
上述例子,x的值是0-10之前的整数,在该模式匹配中有4个case语句,分别对应x值为0、1、2和其他的的情况,当匹配到了一种情况时,就不会继续往下匹配
match表达式通常会有结果值,因此可以写成函数形式
def matchDemo(x:Int):String = x match{
case 0 => "0"
case 1 => "1"
case 2 => "2"
case _ => "其他"
}
println(matchDemo(2)) // 2
println(matchDemo(6)) // 其他
上述match表达式结果值为String类型,故函数返回值也应该为String类型,函数的形参为x,故match前的变量也为x
模式中的变量
如果在case关键字后跟变量名,那么match前表达式的值会赋给那个变量
def matchDemo(x:Int):String = x match{
case 0 => "0"
case 1 => "1"
case 2 => "2"
case x => "其他,该数为:"+x // 用变量x接收其他值,在该行中可以用x进行操作
}
println(matchDemo(2)) // 2
println(matchDemo(6)) // 其他,该数为:6
类型匹配
可以匹配对象的任意类型,这样做避免了使用isInstanceOf和asInstanceOf方法
def matchDemo(x:Any):String = x match{
case x:Int => "Int类型"
case x1:Double => "Double类型"
case x2:String => "String类型"
case x3:Char => "Char类型"
case x4:Array(Int) => "Array(Int)类型"
case _ => "其他类型"
}
println(matchDemo(5)) // 大于2的其他
println(matchDemo(-1)) // 小于2的其他
模式守卫
为了让匹配更加具体,可以使用模式守卫,也就是在模式后面加上if 条件语句
def main(args: Array[String]): Unit = {
def matchDemo(x:Int):String = x match{
case _ if x>90 => "优秀"
case _ if x>70 => "良好"
case _ if x>60 => "及格"
case _ => "不及格"
}
println(matchDemo(5)) // 不及格
println(matchDemo(90)) // 良好
}
数组模式匹配
def arrayMatch(arr:Array[String]):String= arr match{
case Array("stu1") => "stu1" // 精准匹配,只匹配Array("stu1")
case Array(x,y,z) => x+","+y+","+z // 匹配三个元素的数组
case Array("stu1",_*) => "stu1 _*" // 匹配以stu1开头的,至少一个元素的数组
case _ => "其他" // 匹配除上述以外的其他数组
}
println(arrayMatch(Array("stu1"))) // stu1
println(arrayMatch(Array("stu","stu1","stu2"))) // stu,stu1,stu2
println(arrayMatch(Array("stu1","stu2"))) // stu1 _*
println(arrayMatch(Array("stu","stu1"))) // 其他
Option模式匹配
option只有两种值,一种是Some 表示有值,一种是None 表示没值。scala中使用 option 用于模式匹配中表示有值没值要比 Null更显得简洁
val map = Map("stu1"->90,"stu2"->86,"stu3"->79)
def optionMatch(name:String)={
val score = map.get(name)
score match{
case Some(score) => name+"的成绩为"+score
case None => name+"暂无成绩"
}
}
println(optionMatch("stu5"))
样例类(case class)的模式匹配
使用了case关键字的类定义就是就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配。
// 以校园人员为例,假设有老师、学生、工人、陌生人四类
object CaseDemo {
def main(args: Array[String]): Unit = {
class Person{
}
// 样例类,继承Person类
case class Teacher(name:String,subject:String) extends Person
case class Student(name:String,className:String) extends Person
case class Worker(name:String,work:String) extends Person
case class Stranger() extends Person
def fun(f:Person):Unit= f match {
case Teacher(name,subject) => println("老师")
case Student(name,className) => println("学生")
case Worker(name,work) => println("工人")
case Straiger() => println("陌生人")
}
println(Stranger()) // 陌生人
println(Teacher("zhangsan","scala")) // 老师
}
}