模式匹配是scala中非常有特色, 非常强大的一种工. 模式匹配, 其实类似于java的switch语法, 即对一个值进行判断, 然后针对不同的条件, 进行不同的处理.
但是scala的模式匹配的功能比java的switch语法的功能强很多, java的只能对值进行匹配, 还是只能int和枚举的值进行匹配. 但是scala的模式匹配除了可以对值进行匹配外, 还可以有以下匹配:
- 对类型进行匹配
- 对Array和List的元素情况进行匹配
- 对case class进行匹配
- 有值或没值(Option)进行匹配.
简单例子
scala是没有java的switch语法, 但提供更强大的match语法, 即模式匹配.
match语法如下: 变量名 match{case 值 => 表达式}
如果值为下划线, 则表示不满足以上所有情况的默认情况处理.
match语法中, 只要一个case分支满足, 则不会继续判断下一个case分支. 这一点跟java不一样, 也避免了忘记写break造成的bug.
例子: 成绩评价
def judgeGrade(grade: String){
grade match{
case "A" => println("Excellent")
case "B" => println("Good")
case "C" => println("Just so so")
case _ => println("you need work harder")
}
}
在模式匹配中使用if守卫
scala的模式匹配语法, 有一个特点在于, 可以在case后的条件判断中, 不仅仅只是提供一个值, 而是可以在值后面再加一个if守卫, 进行双重过滤.
例子: 成绩评价(升级版, 可根据名称给出不同的提示)
def judgeGrade(name:String, grade:String){
grade match{
case "A" => println(name+", you are excellent")
case "B" => println(name+", you are good")
case "C" if name == "jc" => println(name+", you are a good boy, come on")
case "C" => println(name+", you are just so so") //这句必须是在上一句的后面, 不然就永远匹配不到jc
case _ => println("you need to work harder")
}
}
在模式匹配中进行变量赋值
scala的模式匹配语法, 可以将模式匹配的默认情况, 下划线, 替换为一个变量名, 此时模式匹配语法就会将要匹配的值赋值给这个变量, 从而可以在后面的处理语句中使用被匹配的值.
例子: 成绩评价(升级版, 可根据名称给出不同的提示, 并且带成绩)
def judgeGrade(name:String, grade:String){
grade match{
case "A" => println(name+", you are excellent")
case "B" => println(name+", you are good")
case "C" => println(name+", you are just so so")
case _actualGrade if name == "jc" => println(name+", you are a good boy, come on, your grade is "+_actualGrade)
case _actualGrade => println("you need to work harder, your grade is"+_actualGrade)
}
}
对类型进行模式匹配
scala的模式匹配其中一个强大功能就是, 可以直接匹配类型.
例子: 异常处理
import java.io_
def processException(){
e match{
case e1: IllegalArgumentException=> println("that has illegal arguments! exception is: "+e1)
case e2: FileNotFoundException=> println("can not find the file! exception is: "+e2)
case e3: IOException=> println("you got an IOException")
case _: Exception=>println("I have not idea what exception is")
}
}
注意这里要与上面的”模式匹配对值的匹配”进行对比, 知道它们的差异, 匹配值是 case 值=> 表达式, 而匹配类型是case 变量: 类型=>表达式. 所以匹配类型默认就可以进行变量赋值. 而匹配值则需要以下划线来定义新的变量来赋值.
对Array和List进行模式匹配
对Array进行模式匹配, 分别可以匹配带有指定元素的数组, 带有指定元素个数的数组, 指定以某个元素打头的数组
对List进行模式匹配, 跟Array类似, 但是需要List特有的::操作符
例子: 对朋友打招呼
def greeting(peoples: Array[String]){
peoples match{
case Array("jc")=> println("Hi, jc!")
case Array(girl1, girl2, girl3)=> println("Hi, girls, nice to meet you. "+girl1+" and "+girl2+" and "+ girl3)
case Array("jc",_*)=> println("Hi, jc, please introduce your friends to me.")
case _=> println("hey guys, who are you!")
}
}
var a = Array("jc")
greeting(a)
a = Array("jc","jay","jack")
greeting(a)
a = Array("jc","jay","jack","john")
greeting(a)
a = Array("jay","jack","john","johnny")
greeting(a)
def greeting(peoples: List[String]){
peoples match{
case "jc"::Nil=> println("Hi, jc!")
case girl1::girl2::girl3::Nil=> println("Hi, girls, nice to meet you. "+girl1+" and "+girl2+" and "+girl3)
case "jc"::tail=> println("Hi, jc, please introduce your friends to me.")
case _=> println("hey guys, who are you!")
}
}
var a = List("jc")
greeting(a)
a = List("jc","jay","jack")
greeting(a)
a = List("jc","jay","jack","john")
greeting(a)
a = List("jay","jack","john","johnny")
greeting(a)
上面两个功能都一样, case语句分别是一下功能: 只有jc元素的, 3个元素的集合, jc元素的打头的, 其他情况的.
case class与模式匹配
scala提供了一种特殊的累, 就是用case class的类, 这种类称为样例类. 样例类其实有点类似于严格定义的JavaBean, 只定义了field, 并且由scala编译时自动提供getter和setter方法, 但是没有其他方法.
除此之外,scala会自动为样例类定义伴生对象, 也就是object, 并且定义了apply方法, 该apply方法的参数跟主构造函数的参数一样, 病返回样例类.
简单的说, 样例类简化了定义类和实例化类的语法.
例子: 学校广播
class Person
case class Teacher(name:String, subject:String) extends Person
case class Student(name:String, classroom:String) extends Person
def broadcast(p: Person){
p match{
case Teacher(name, subject)=> println("教"+subject+"的"+name+"老师马上到教导处来")
case Student(name, classroom)=> println(classroom+name+"马上到教导处来")
case _=>println("三年二班")
}
}
val t = Teacher("周杰伦","音乐")
val s = Student("周杰伦","三二班")
broadcast(t)
broadcast(s)
Option与模式匹配
scala有一种特殊的类型叫Option, Option有两个值, 一种是Some, 代表有值, 一种是None代表没有值.
Option通常会用于模式匹配中, 用于判断某个变量是否有值还是没有值, 这比null来的更加语义化.
例子: 成绩查询
val grades = Map("jc"->"A","jay"->"B","jack"->"M")
def getGrade(name:String){
var grade = grades.get(name)
grade match{
case Some(grade)=> println("Hi "+name+", your grade is "+grade)
case None=> println("Sorry "+name+", your grade is not in the system.")
}
}
getGrade("jc")
getGrade("jay")
getGrade("jack")
getGrade("john")