模式匹配
基本语法
- 模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需要匹配时,会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _分支,类似于 Java 中 default 语句。
val x:Int = 2
val y:String = x match {
case 1 => "one"
case 2 => "two"
case 3 => "three"
case _ => "null"
}
println(y)
- 如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句,若此时没有 case _ 分支,那么会抛出 MatchError。
- 每个 case 中,不需要使用 break 语句,自动中断 case。
- match case 语句可以匹配任何类型,而不只是字面量。
- => 后面的代码块,直到下一个 case 语句之前的代码是作为一个整体执行,可以使用{}括起来,也可以不括。
模式守卫
- 说明:如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。
def abs(x:Int) = x match {
case i:Int if i>=0 => i
case j:Int if j<0 => -j
case _ => "gg"
}
println(abs(-9))
模式匹配类型
匹配常量
- Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。
def describeConst(x:Any):String = x match {
case 1 => "Int one"
case "hello" => "String hello"
case true => "Boolean true"
case '+' => "Char +"
case _ => "Null"
}
println(describeConst(1))
println(describeConst("hello"))
println(describeConst(true))
println(describeConst('+'))
println(describeConst(1231))
匹配类型
- 需要进行类型判断时,可以使用前文所学的 isInstanceOf[T]和 asInstanceOf[T],也可使用模式匹配实现同样的功能。
def describeConst(x:Any):String = x match {
case i:Int => "Int " + i
case s:String => "String " + s
case b:Boolean => "Boolean " + b
case c:Char => "Char " + c
case list:List[String] => "List " + list
case array: Array[Int] => "Array " + array
case _ => "Null"
}
println(describeConst(1))
println(describeConst("hello"))
println(describeConst(true))
println(describeConst('+'))
println(describeConst(List("1","11")))
println(describeConst(List(1,2,3)))
println(describeConst(Array(1,2,3)))
println(describeConst(Array("1","11")))
匹配数组
- scala 模式匹配可以对集合进行精确的匹配,例如匹配只有两个元素的、且第一个元素为 0 的数组。
for (arr <- Array(
Array(0),
Array(1,0),
Array(0,1,0),
Array(1,1,0),
Array(1,1,0,1),
Array("hello", 90)
)
){
var result = arr match {
case Array(0) => "0"
case Array(x,y) => x + "," + y
case Array(0,_*) => "以0开头的数组"
case _ => "something else"
}
println(result)
}
匹配列表
for (arr <- List(
List(0),
List(1,0),
List(0,1,0),
List(1,1,0),
List(1,1,0,1),
List("hello", 90)
)
){
val result = arr match {
case List(0) => "0"
case List(x,y) => x + "," + y
case List(0,_*) => "以0开头的数组"
case _ => "something else"
}
println(result)
}
val list = List(1,2,3,4,5,6)
list match {
case first::second::rest => println(s"first:$first second:$second rest:$rest")
case _ => println("something else")
}
匹配元组
for (tuple <- List(
(0, 1),
(0, 0),
(0, 1, 0),
(0, 1, 1),
(1, 23, 56),
("hello", true, 0.5)
)){
val result = tuple match {
case (a, b) => "" + a + "," + b
case (0, _) => "(0, _)"
case (a, 1, _) => "(a, 1, _)" + a
case _ => "something else"
}
println(result)
}
匹配对象及样例类
- 说明:
- 当将 User("zhangsan", 11)写在 case 后时[case User("zhangsan", 11) => "yes"],会默认调用 unapply 方法(对象提取器),user 作为 unapply 方法的参数,unapply 方法将 user 对象的 name 和 age 属性提取出来,与 User("zhangsan", 11)中的属性值进行匹配
- case 中对象的 unapply 方法(提取器)返回 Some,且所有属性均一致,才算匹配成功,属性不一致,或返回 None,则匹配失败。
- 若只提取对象的一个属性,则提取器为 unapply(obj:Obj):Option[T]
- 若提取对象的多个属性,则提取器为 unapply(obj:Obj):Option[(T1,T2,T3…)]
- 若提取对象的可变个属性,则提取器为 unapplySeq(obj:Obj):Option[Seq[T]]
object test5 {
def main(args: Array[String]): Unit = {
val student = new Student("wrq", 23)
val result = student match {
case Student("wrq", 23) => "wrq, 23"
case _ => "ELse"
}
println(result)
}
}
class Student(val name: String, val age: Int){
}
object Student{
def apply(name:String, age:Int):Student = new Student(name, age)
def unapply(student: Student):Option[(String, Int)] = {
if (student == null){
None
}else{
Some(student.name, student.age)
}
}
}
- 样例类:
- 语法:case class Person (name: String, age: Int)
- 说明
- 样例类仍然是类,和普通类相比,只是其自动生成了伴生对象,并且伴生对象中自动提供了一些常用的方法,如 apply、unapply、toString、equals、hashCode 和 copy。
- 样例类是为模式匹配而优化的类,因为其默认提供了 unapply 方法,因此,样例类可以直接使用模式匹配,而无需自己实现 unapply 方法。
- 构造器中的每一个参数都成为 val,除非它被显式地声明为 var(不建议这样做)