Scala学习笔记
模式匹配
-
模式匹配类似于java中的switch语法,但是要更加强大。
-
在模式匹配中,采用match关键字,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果成功,那么执行对应的逻辑代码,反之则继续执行下一个分支进行判断。如果所有的case都不成功,则会执行case _分支,类似于switch语法中的default语句。
-
基本语法:
/** a match { case '1' => print(1) case '2' => print(2) case _ => print('其他') } **/
- 如果所有的case都不匹配,那么会匹配case_分支,若没有该分支,则抛出MatchError
- 每个case中,都不用break语句,自动中断case
- match case语句可以匹配任何类型,不只是字面量
- => 后面的代码块会作为一个整体执行,可以用花括号{},也可以不用
模式守卫
-
如果想要匹配某个范围内的数据,就需要用到模式守卫,即在模式匹配中添加条件守卫
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(34),abs(-12),abs(12)) } /** 输出结果为: (34,12,12) **/
模式匹配类型
-
匹配常量
- scala中,模式匹配中可以匹配所有的字面量,包括字符串、字符、数字、布尔值等等。
println(test(6)) println(test("6")) println(test(6>5)) println(test('6')) def test(x:Any) = x match { case 6 => "Int 6" case "6" => "String 6" case true => "Boolean true" case '6' => "Char 6" case _ => "_" } /** 输出结果为: Int 6 String 6 Boolean true Char 6 **/
-
匹配类型
- 在scala的模式匹配中,需要进行类型判断的时候,可以通过isInstanceOf[]或asInstanceOf[],也可以使用模式匹配实现相同的功能
- 注意,在模式匹配中会出现对集合的范式擦除的问题,只有数组例外,可以保留范式。
def main(args: Array[String]): Unit = { println(caseType(List(1,2,3))) println(caseType(List("123"))) println(caseType(Array(1,2,3))) println(caseType(Array("123"))) def caseType(x:Any)=x match { case ls:List[String] => "String list" case li:List[Int] => "Int list" case arrays:Array[String] => "String array" case ai:Array[Int] => "Int array" case _ => "_" } } /** 可以在下面的结果中看到结果中list的泛型被擦除了, 不论泛型为那种都被在前的 case ls:List[String] => "String list"这行吸收了 而数组array则没有这种问题 输出结果为: String list String list Int array String array **/
-
匹配数组
- scala模式匹配可以对集合进行精确的匹配,如只有两个元素的数组、第一个元素为0的数组等
def main(args: Array[String]): Unit = { for (a <- Array(Array(1),Array(0),Array(1,3),Array(1,2,3,4),Array(0,1,2))){ val result = a match { case Array(0) => "0" case Array(x,y) => x+","+y case Array(0,_*) => "start with 0" case _ => "_" } println(result) } } /** 输出结果为: _ 0 1,3 _ start with 0 **/
-
匹配对象
- 在伴生对象中实现unapply方法,提供提取器,case案例在匹配时会调用提取器提取对象中的属性进行匹配。
- case中对象的unapply方法返回Some,且所有属性均一致时才算匹配成功,属性不一致,返回None,匹配失败。
- 根据匹配需求不同,有时候需要匹配的属性也不同,这些时候所用的提取器也不尽相同:
- 若只提取一个属性,则用: unapply(obj:Obj):Option[T]
- 若提取多个属性,则用:unapply(obj:Obj):Option[(T1,T2,T3,T4,…)]
- 若提取可变个属性,则用:unapply(obj:Obj):Option[Seq[T]]
class User(val name:String,val age:Int) object User{ def apply(name: String, age: Int): User = new User(name, age) def unapply(user: User): Option[(String, Int)] = { if (user == null){ None }else { Some(user.name, user.age) } } } object TestCaseObject { def main(args: Array[String]): Unit = { val user:User = User("Zhan",12) val result = user match { case User("Zhan",12) => "match" case _ => "_" } println(result) } } /** 输出结果为: match **/
-
样例类:
- 通过case修时的类为样例类。
- 样例类依然是类,只是其自动生成了伴生对象,且自动实现了一些常用的方法,如apply、unapply、toString、equals、hashCode和copy等
- 样例类是为模式匹配而优化的类,其默认提供unapply方法,因此可以直接用于模式匹配
- 构造器的每个参数都默认为val,除非它被显式的声明为var
case class User(name:String,age:Int) object TestCaseClass { def main(args: Array[String]): Unit = { val user = User("Alice",12) val result = user match { case User("Alice",12) => "match" case _ => "_" } println(result) } } /** 输出结果为: match **/
- 通过case修时的类为样例类。
其他情况下的模式匹配
-
声明变量中的模式匹配
- 在声明变量时可以通过各种模式匹配套用格式,获取满足条件的值
object TestCase2 { def main(args: Array[String]): Unit = { val (x,y) = (2,4) println(x,y) val Array(a,b,c,_*) = Array(1,2,3,4,5,6) println(a,b,c) } } /** (2,4) (1,2,3) **/
-
for循环中的模式匹配
object TestCaseFor { def main(args: Array[String]): Unit = { val map = Map(1->"1",2->"2",3->"3") for ((k,v) <- map){ println(k,v) } } } /** (1,1) (2,2) (3,3) **/
版权声明:本文为airleaya原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。