模式匹配

Scala没有Java中的switch case,它有一个更加强大的模式匹配机制,可以应用到很多场合。

Scala的模式匹配可以匹配各种情况,比如变量的类型、集合的元素、有值或无值。

模式匹配的基本语法结构:变量 match { case 值 => 代码 }

模式匹配match case中,只要有一个case分支满足并处理了,就不会继续判断下一个case分支了,不需要使用break语句。这点与Java不同,Java的switch case需要用break阻止。如果值为下划线,则代表不满足以上所有情况的时候如何处理。

模式匹配match case最基本的应用,就是对变量的值进行模式匹配。match是表达式,与if表达式一样,是有返回值的。

除此之外,Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配。

字符和字符串匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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("我不认识你...")
}
}

守卫式匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 所谓守卫就是添加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)
}
}

匹配类型

Scala的模式匹配还有一个强大的功能,它可以直接匹配类型,而不是值。这一点是Java的switch case做不到的。

匹配类型的语法:case 变量 : 类型 => 代码,而不是匹配值的“case 值 => 代码”这种语法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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)
}

匹配数组、元组、集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def main(args: Array[String]): Unit = {
val arr = Array(0, 3, 5)
//对Array数组进行模式匹配,分别匹配:
//带有指定个数元素的数组、带有指定元素的数组、以某元素开头的数组
arr match {
//指定0开头的含有三个元素
case Array(0, x, y) => println(x + " " + y)
//只有0一个元素
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")
//带有指定元素0的列表
case 0 :: Nil => println("only 0")
//以1元素开头的列表
case 1 :: tail => println("1 ...")
case _ => println("something else")
}

val tuple = (1, 3, 7)
tuple match {
//以1开头,包含三个元素的元组
case (1, x, y) => println(s"1, $x , $y")
//以5结尾,包含三个元素的元组
case (_, z, 5) => println(z)
case _ => println("else")
}
}

样例类

case class样例类是Scala中特殊的类。当声明样例类时,以下事情会自动发生:

  • 主构造函数接收的参数通常不需要显式使用var或val修饰,Scala会自动使用val修饰

  • 自动为样例类定义了伴生对象,并提供apply方法,不用new关键字就能够构造出相应的对象

  • 将生成toString、equals、hashCode和copy方法,除非显示的给出这些方法的定义

  • 继承了Product和Serializable这两个特质,也就是说样例类可序列化和可应用Product的方法

case class是多例的,后面要跟构造参数,case object是单例的。

此外,case class样例类中可以添加方法和字段,并且可用于模式匹配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package lagou.cn.part07

class Amount
//样例类中主构造器的参数默认用val修饰
//样例类中自动生成apply方法
case class Dollar(value: Double) extends Amount

case class Currency(value: Double, unit: String) extends Amount

case object Nothing extends Amount

object CaseClassDemo {
def main(args: Array[String]): Unit = {
judgeIdentity(Dollar(10.0))
judgeIdentity(Currency(20.0, "100"))
judgeIdentity(Nothing)
}

def judgeIdentity(amt: Amount): Unit = {
amt match {
case Dollar(value) => println(s"$value")
case Currency(value, unit) => println(s"$value $unit")
case Nothing => println("nothing")
}
}
}

Option与模式匹配

Scala Option选项类型用来表示一个值是可选的,有值或无值。

Option[T] 是一个类型为 T 的可选值的容器,可以通过get()函数获取Option的值。如果值存在,Option[T] 就是一个 Some。如果不存在,Option[T] 就是对象 None 。

Option通常与模式匹配结合使用,用于判断某个变量是有值还是无值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package lagou.cn.part07

object OptionDemo {
val grades = Map("jacky" -> 90, "tom" -> 80, "jarry" -> 60)

def getGrade(name: String): Unit = {
val grade: Option[Int] = grades.get(name)
grade match {
case Some(grade) => println("成绩是:" + grade)
case None => println("没有此人成绩!")
}
}

def main(args: Array[String]): Unit = {
getGrade("jacky")
getGrade("lisi")
}
}