vlambda博客
学习文章列表

Scala总结之模式匹配

模式匹配是什么


       采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需要匹配时, 会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句。

有什么作用


在java代码规范中,有一条规则是说“当分支数大于2时,选用switch case,不要用if else”。在Scala语言中,没有java中的switch case语法,但是引入了更强大的match case语法来满足这点。除了能够代替java switch case语法功能,switch case还可以匹配对象、范围匹配、类型匹配等等功能。


与java switch对比




相同点

1、 都是用来避免多分支的情况下,去使用很多个if else分支,代码可以更加的清晰。

不同点

1、 scala中match case,不存在case击穿,不需要使用“break”(scala中也没有break关键字)。而java case分支不加break,就会出现case击穿现象。

2、 Java 中 case后面只能放int、byte、char、short、string、枚举类型,scala不限于上述范围,支持scala collection、对象、样例类等,scala中支持的类型匹配,避免在代码中使用isInstanceOf、asInstanceOf方法。类型匹配代码说明如下:

val i = 1; val value=if(i==0){ Array("zsf") }else if(i==1){ Map("zsf"->"zsf")}val result = value match { case a:Array[String] => 1 case b:Map[String,String] => 2 case b:Map[Int,String] => 3 case b:List[String] => 4 case _ => 0}println(s"result is :$result")

运行结果如下:

result is :2


3、 scala中用_表示默认分支,java中用default来表示默认分支。当case _分支位于第一个case分支时,后面的case分支永远不能执行到。

验证代码如下:

val value = "zsf"val result = value match { case _ => "unknow value"   case "zsf" => "match is zsf"}println(s"result is $result")

输出结果:

result is unknow value


4、 scala中如果没有
一个分支能够匹配上,会抛出“scala.MatchError”,java中不会有异常抛出,程序正常结束。

5、 scala中的match case是一个有返回值的语句,因为scala match case是一个表达式。

6、 利用守卫,scala中的match case可以达到范围匹配的效果。下面代码便可实现10-20时匹配第一个分支,小于10时匹配第二个分支的效果。

val value =19 value match { case _ if value>10 &&value <20 =>println("10~20") case _ if value<10=>println("<10") }

7、 scala支持匹配对象

对象匹配,什么才算是匹配呢?规则如下:
a) case 中对象的unapply方法(对象提取器)返回Some集合则为匹配成功 

b) 返回 None 集合则为匹配失败。

下面定义了两个自定义类——woman、man,他们的区别在于woman的提取器unapply返回None,而man的提取器返回Some。

 class Woman(val name:String){ }  object Woman{ def unapply(man: Man): Option[(String, Int)] = { None } }  class Man(val name:String,val age:Int){}  object Man{ def unapply(man: Man): Option[(String, Int)] = { Some(man.name,man.age)   }   def apply(name: String, age: Int): Man = new Man(name, age) }

试验代码

package baseobject ObjectMatch { def main(args: Array[String]): Unit = { val womanResult = new Woman("xh") match { case Woman(name) => s"woman is $name" case Man(name,age) => s"name is $name;age is $age" case List(1,a) => s"1打头的,第二个元素是$a 的list" case _ =>"no case to match." } val manResult = new Man("xh",29) match { case Woman(name) => s"woman is $name" case Man(name,age) => s"name is $name;age is $age" case List(1,a) => s"1打头的,第二个元素是$a 的list" case _ =>"no case to match." } println(s"womanResult is $womanResult")     println(s"manResult is $manResult")   } }

验证结果

womanResult is no case to match.manResult is name is xh;age is 29