Scala是没有Java中的switch case语法的,相对应的,Scala提供了更加强大的match case语法,即模式匹配,类替代switch case,match case也被称为模式匹配
Scala的match case与Java的switch case最大的不同点在于,Java的switch case仅能匹配变量的值,比1、2、3等;而Scala的match case可以匹配各种情况,比如变量的类型、集合的元素、有值或无值
match case的语法如下:变量 match { case 值 => 代码 }。如果值为下划线,则代表了不满足以上所有情况下的默认情况如何处理。此外,match case中,只要一个case分支满足并处理了,就不会继续判断下一个case分支了。(与Java不同,java的switch case需要用break阻止)
Scala中类似Java的switch代码:
注意:
Scala的模式匹配只会匹配到一个分支,不需要使用break语句,因为它不会掉入到下一个分支。 match是表达式,与if表达式一样,是有值的:
object PatternDemo { def main(args: Array[String]): Unit = { var sign = 0 val ch: Char = 'p' val valchar = 'p' var digit = 0 //match 是表达式 ch match { case '+' => sign = 1 case '-' => sign = -1 //使用|分割多个选项 case '*' | 'x' => sign = 2 //可以使用变量 case valchar => sign = 3 //case _ 类似Java中的default // 如果没有模式能匹配,会抛出MacthError //可以给模式添加守卫 case _ if Character.isDigit(ch) => digit = Character.digit(ch, 10) } println("sign = "+ sign) } }Scala的模式匹配一个强大之处就在于,可以直接匹配类型,而不是值!!!这点是java的switch case绝对做不到的。
可以对表达式类型进行匹配:
val arr = Array("hs", 1, 2.0, 'a') val obj = arr(Random.nextInt(4)) println(obj) obj match { case x: Int => println(x) case s: String => println(s.toUpperCase) case _: Double => println(Int.MaxValue) case _ => 0 }注意: 当你在匹配类型的时候,必须给出一个变量名,否则你将会拿对象本身来进行匹配:
obj match { case _: BigInt => Int.MaxValue // 匹配任何类型为BigInt的对象 case BigInt => -1 // 匹配类型为Class的BigInt对象 }匹配发生在运行期,Java虚拟机中泛型的类型信息是被擦掉的。因此,你不能用类型来匹配特定的Map类型。
case m: Map[String, Int] => ... // error // 可以匹配一个通用的映射 case m: Map[_, _] => ... // OK // 但是数组作为特殊情况,它的类型信息是完好的,可以匹配到Array[Int] case m: Array[Int] => ... // OK字符串匹配
/** * 模式匹配-字符串 */ object MatchString { def main(args: Array[String]): Unit = { val arr = Array("asan", "jiangzi", "gulingling", "zhenshauang") val name = arr(Random.nextInt(arr.length)) println(name) name match { case "zhoudongyu" => println("阿三") case "yangzi" => println("酱紫") case "guanxiaotong" => println("孤零零") case "zhengshuang" => println("真爽") case _ => println("Nothing ...") } } }数组匹配
对Array进行模式匹配,分别可以匹配带有指定元素的数组、带有指定个数元素的数组、以某元素打头的数组.
val arr1 = Array(1,1) val res = arr1 match { case Array(0) => "0" //匹配包含0的数组 case Array(x, y) => s"$x $y" // 匹配任何带有两个元素的数组,并将元素绑定到x和y case Array(0, _*) => "0..." //匹配任何以0开始的数组 case _ => "something else" }列表匹配
val lst = List(1,2) val res2 = list match { case 0 :: Nil => "0" case x :: y :: Nil => x + " " + y case 0 :: tail => "0 ..." case _ => "something else" }元组匹配
var pair = (1,2) val res3 = pair match { case (0, _) => "0 ..." case (y, 0) => s"$y 0" case _ => "neither is 0" }在Scala中样例类是一中特殊的类,样例类是不可变的,
可以通过值进行比较,可用于模式匹配。
定义一个样例类:
构造器中每一个参数都是val,除非显示地声明为var
伴生对象提供apply ,让你不使用new关键字就能构造出相应的对象
case class Point(x: Int, y: Int)创建样例类对象:
val point = Point(1, 2) val anotherPoint = Point(1, 2) val yetAnotherPoint = Point(2, 2) //访问对象值 point.x point.x =1 //不可以通过值对样例类对象进行比较:
if (point == anotherPoint) { println(point + " and " + anotherPoint + " are the same.") } else { println(point + " and " + anotherPoint + " are different.") } // Point(1,2) 和 Point(1,2)一样的. if (point == yetAnotherPoint) { println(point + " and " + yetAnotherPoint + " are the same.") } else { println(point + " and " + yetAnotherPoint + " are different.") } // Point(1,2)和Point(2,2)是不同的.在模式匹配中使用样例类:
样例类是一种特殊的类,可用于模式匹配,case class是多例的,后面要跟构造参数,case object是单例的。
object CaseClassMatch { //定义样例类 abstract class Notification case class Email(sender: String, title: String, body: String) extends Notification case class SMS(caller: String, message: String) extends Notification case class VoiceRecording(contactName: String, link: String) extends Notification //基于样例类的模式匹配 def showNotification(notification: Notification): String = { notification match { case Email(email, title, _) => s"You got an email from $email with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" case VoiceRecording(name, link) => s"you received a Voice Recording from $name! Click the link to hear it: $link" } } def main(args: Array[String]): Unit = { val someSms = SMS("12345", "Are you there?") val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123") println(showNotification(someSms)) //结果:You got an SMS from 12345! Message: Are you there? println(showNotification(someVoiceRecording)) //结果:you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123 } }声明样例类 ,以下几件事会自动发生:
提供unapply方法,让模式匹配可以工作
生成toString equals hashCode copy 方法,除非显示给出这些方法的定义。
在Scala中Option类型样例类用来表示可能存在或也可能不存在的值(Option的子类有Some和None)。Some包装了某个值,None表示没有值。
object OptionDemo { def main(args: Array[String]) { val map = Map("a" -> 1, "b" -> 2) val v = map.get("b") match { case Some(i) => i case None => 0 } println(v) //更好的方式 val v1 = map.getOrElse("c", 0) println(v1) } }被包在花括号内没有match的一组case语句是一个偏函数,它是PartialFunction[A, B]的一个实例,A代表参数类型,B代表返回类型,常用作输入模式匹配
一个是apply()方法,直接调用可以通过函数体内的case进行匹配,返回结果; 另一个是isDefinedAt()方法,可以返回一个输入,是否跟任何一个case语句匹配
object PartialFunctionDemo { def f1: PartialFunction[String, Int] = { case "one" => 1 case "two" => 2 case _ => -1 } def main(args: Array[String]) { //调用f.apply("one") println(f1.apply("one")) println(f1("one")) println(f1.isDefinedAt("three")) //抛出MatchError println(f1("three")) } }