vlambda博客
学习文章列表

【必会】Scala之模式匹配和样例类

大家好,我是勾叔。今天和大家聊一下模式匹配和样例类。

1. 模式匹配

Scala没有Java中的switch case,它有一个更加强大的模式匹配机制,可以应用到很多场合。Scala的模式匹配可以匹配各种情况,比如变量的类型、集合的元素、有值或无值。
模式匹配的基本语法结构:变量 match { case 值 => 代码 },模式匹配match case中,只要有一个case分支满足并处理了,就不会继续判断下一个case分支了,不需要使用break语句。这点与Java不同,Java的switch case需要用break阻止。如果值为下划线,则代表不满足以上所有情况的时候如何处理。
模式匹配match case最基本的应用,就是对变量的值进行模式匹配。match是表达式,与if表达式一样,是有返回值的。
除此之外,Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配。


2. 字符和字符串匹配

 
   
   
 
def main(args: Array[String]): Unit = {
val charStr = '6'
charStr match {
case '+' => println("匹配上了加号")
case '-' => println("匹配上了减号")
case '*' => println("匹配上了乘号")
case '/' => println("匹配上了除号")
//注意:不满足以上所有情况,就执行下面的代码
case _ => println("都没有匹配上,我是默认值")
}
}
def main(args: Array[String]): Unit = {
val arr = Array("hadoop", "zookeeper", "spark")
val name = arr(Random.nextInt(arr.length))
name match {
case "hadoop" => println("大数据分布式存储和计算框架...")
case "zookeeper" => println("大数据分布式协调服务框架...")
case "spark" => println("大数据分布式内存计算框架...")
case _ => println("我不认识你...")
}
}


3. 守卫式匹配

所谓守卫式匹配就是在模式匹配结构中添加if语句,代码演示如下:
 
   
   
 
object MatchDemo {
def main(args: Array[String]): Unit = {
//守卫式
val character = '*'
val num = character match {
case '+' => 1
case '-' => 2
case _ if character.equals('*') => 3
case _ => 4
}
       println(character + " " + num)
}
}


4. 匹配类型

Scala的模式匹配还有一个强大的功能,它可以直接匹配类型,而不是值。这一点是Java的switch case做不到的。匹配类型的语法:case 变量 : 类型 => 代码,而不是匹配值的“case 值 => 代码”这种语法,代码演示如下:
 
   
   
 
def main(args: Array[String]): Unit = {
val a = 3
val obj = if(a == 1) 1
else if(a == 2) "2"
else if(a == 3) BigInt(3)
else if(a == 4) Map("aa" -> 1)
else if(a == 5) Map(1 -> "aa")
else if(a == 6) Array(1, 2, 3)
else if(a == 7) Array("aa", 1)
else if(a == 8) Array("aa")
val r1 = obj match {
case x: Int => x
case s: String => s.toInt
// case BigInt => -1 //不能这么匹配
case _: BigInt => Int.MaxValue
case m: Map[String, Int] => "Map[String, Int]类型的Map集合"
case m: Map[_, _] => "Map集合"
case a: Array[Int] => "It's an Array[Int]"
case a: Array[String] => "It's an Array[String]"
case a: Array[_] => "It's an array of something other than Int"
case _ => 0
}
   println(r1 + ", " + r1.getClass.getName)
}


5. 匹配数组、元组、集合

 
   
   
 
def main(args: Array[String]): Unit = {
val arr = Array(0, 3, 5)
//对Array数组进行模式匹配,分别匹配:
//带有指定个数元素的数组、带有指定元素的数组、以某元素开头的数组
arr match {
case Array(0, x, y) => println(x + " " + y)
case Array(0) => println("only 0")
//匹配数组以1开始作为第一个元素
case Array(1, _*) => println("1 ...")
case _ => println("something else")
}
   val list = List(3, -1)
//对List列表进行模式匹配,与Array类似,但是需要使用List特有的::操作符
//构造List列表的两个基本单位是Nil和::,Nil表示为一个空列表
//tail返回一个除了第一元素之外的其他元素的列表
//分别匹配:带有指定个数元素的列表、带有指定元素的列表、以某元素开头的列表
list match {
case x :: y :: Nil => println(s"x: $x y: $y")
case 0 :: Nil => println("only 0")
case 1 :: tail => println("1 ...")
case _ => println("something else")
}
   val tuple = (1, 3, 7)
tuple match {
       case (1, x, y) => println(s"1, $x , $y")
case (_, z, 5) => println(z)
case _ => println("else")
  }
}


6. 样例类

case class样例类是Scala中特殊的类。当声明样例类时,以下事情会自动发生:
  • 主构造函数接收的参数通常不需要显式使用var或val修饰,Scala会自动使用val修饰;
  • 自动为样例类定义了伴生对象,并提供apply方法,不用new关键字就能够构造出相应的对象;
  • 将生成toString、equals、hashCode和copy方法,除非显示的给出这些方法的定义;
  • 继承了Product和Serializable这两个特质,也就是说样例类可序列化和可应用Product的方法。
case class是多例的,后面要跟构造参数,case object是单例的。此外,case class样例类中可以添加方法和字段,并且可用于模式匹配,代码演示如下:
 
   
   
 
class Amount
//定义样例类Dollar,继承Amount父类
case class Dollar(value: Double) extends Amount
//定义样例类Currency,继承Amount父类
case class Currency(value: Double, unit: String) extends Amount
//定义样例对象Nothing,继承Amount父类
case object Nothing extends Amount
object CaseClassDemo {
def main(args: Array[String]): Unit = {
judgeIdentity(Dollar(10.0))
judgeIdentity(Currency(20.2,"100"))
judgeIdentity(Nothing)
}
   //自定义方法,模式匹配判断amt类型
def judgeIdentity(amt: Amount): Unit = {
amt match {
case Dollar(value) => println(s"$value")
case Currency(value, unit) => println(s"Oh noes,I got $unit")
case Nothing => println("Oh,GOD!")
}
}
}


7. Option与模式匹配

Scala Option选项类型用来表示一个值是可选的,有值或无值。Option[T] 是一个类型为 T 的可选值的容器,可以通过get()函数获取Option的值。如果值存在,Option[T] 就是一个 Some。如果不存在,Option[T] 就是对象 None 。Option通常与模式匹配结合使用,用于判断某个变量是有值还是无值,代码演示如下:
 
   
   
 
object OptionMatch {
val grades = Map("jacky" -> 90, "tom" -> 80, "jarry" -> 95)
def getGrade(name: String): Unit = {
val grade = grades.get(name)
grade match {
case Some(grade) => println("成绩:" + grade)
case None => println("没有此人成绩!")
}
}
def main(args: Array[String]): Unit = {
getGrade("jacky")
getGrade("张三")
}
}

大家如果想进行更深入的了解和学习,请关注勾叔谈大数据参与更多互动。



推荐阅读: