基本概念
模式匹配是采用了match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断;当所有的都匹配不到时,就会执行case _ 分支,类似于Java中default语句。
守卫
基本概念
如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。
案例实操
val ch = 10
ch match {
case '+' => sign = 1
case '-' => sign = -1
case _ if ch.toString.equals("10") => digit = 10
case _ => sign = 2
}
注意:模式总是从上往下进行匹配;如果带守卫的这个模式不能匹配,则捕获所有的模式(case _)会被用来尝试进行匹配。
模式中的变量
基本概念
如果在case关键字后跟变量名,那么匹配的表达式会被赋值给那个变量。
案例实操
val ch = 'U'
ch match {
case '+' => println("ok")
case mychar => println("ok~" + mychar)
case _ => println("ok~")
}
// 输出:ok~U
类型匹配
基本概念
在Scala中进行类型匹配时,更倾向于使用这样的模式匹配方式,而不是使用isInstanceOf 操作符。
案例操作
// 类型匹配, obj 可能有如下的类型
val a = 4
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")
// 根据obj的类型进行匹配
val result = obj match {
case a : Int => a
case b : Map[String, Int] => "对象是一个字符串-数字的Map集合"
case c : Map[Int, String] => "对象是一个数字-字符串的Map集合"
case d : Array[String] => "对象是一个字符串数组"
case e : Array[Int] => "对象是一个数字数组"
case f : BigInt => Int.MaxValue
case g : Array[Any] => "任意类型的数组"
case _ => "啥也不是"
}
println(result) // 输出:对象是一个字符串-数字的Map集合
注意事项:
- 在进行类型匹配时,编译器会预先检测是否可能的匹配,如果没有的话就会报错
- Map[String,Int] 和 Map[Int,String]是两种不同的类型
- 如果 case _ 出现在match中间,表示隐藏变量名,就是不使用,而不是表示默认匹配
匹配数组,列表和元组
匹配数组
arr match {
case Array(0) => "0"
case Array(x, y) => ArrayBuffer(y,x) // 转变为可变数组
case Array(0, _*) => "以0开头和数组"
case _ => "什么集合都不是"
}
详解:第一个模式匹配包含0的数组;第二个模式匹配任何带有两个元素的数组,并将两个元素存入到可变数组ArrayBuffer中,第三个表达式匹配任何以零开始的数组。
匹配列表
list match {
case 0 :: Nil => "0" // Nil 表示后面没有值
case x :: y :: Nil => x + " " + y //
case 0 :: tail => "0 ..." // tail表示后面0到多个参数
case _ => "something else"
}
详解:第一个模式匹配表示列表只有一个元素并且为0;第二个表达式匹配任何带有两个元素的列表;第三个表达式匹配任何以0开始的列表。
匹配元组
pair match { //
case (0, _) => "0 ..." // _ 表示忽略这个数据
case (y, 0) => y //
case (x, y) => (y, x)
case _ => "other"
}
详解:第一个表达式匹配以0开头的元组,第二个表达式匹配第一个元素为任意值第二个元素为0,第三个表达式匹配任意两个元素的元组。
for表达式中的模式
基础概念
我们可以在for推导式中使用带变量的模式;对每一个遍历到的值,这些变量都会被绑定;使得我们可以方便地遍历映射。
案例操作
val map = Map("A"->1, "B"->0, "C"->3)
//说明: 只遍历出 value = 0 的key-value,其他的会被过滤掉
for ((k, 0) <- map) {
println(k + " --> " + 0)
}
//说明: 相当于守卫的功能,是上面代码的另一种写法
for ((k, v) <- map if v == 0) {
println(k + " ---> " + v)
}
样例类
基础概念
样例类是一种特殊的类,他们经过优化以被用于模式匹配。还有就是样例类都是经过序列化操作的。
案例操作
abstract class Amount
case class Dollar(value: Double) extends Amount
case class Currency(value: Double, unit: String) extends Amount
样例类注意事项:
- 构造器中的每一个参数都称为val——除非它被显式地声明为var
- 在伴生对象中提供apply方法让你不用new关键字就能构造出相应的对象
- 将会自动生成 toString,equals,hashCode和copy方法
- 样例类是为模式匹配而优化的类