Scala 系列(十一)—— 模式匹配
阿新 • • 發佈:2019-12-31
一、模式匹配
Scala 支援模式匹配機制,可以代替 swith 語句、執行型別檢查、以及支援析構表示式等。
1.1 更好的swith
Scala 不支援 swith,可以使用模式匹配 match...case
語法代替。但是 match 語句與 Java 中的 switch 有以下三點不同:
- Scala 中的 case 語句支援任何型別;而 Java 中 case 語句僅支援整型、列舉和字串常量;
- Scala 中每個分支語句後面不需要寫 break,因為在 case 語句中 break 是隱含的,預設就有;
- 在 Scala 中 match 語句是有返回值的,而 Java 中 switch 語句是沒有返回值的。如下:
object ScalaApp extends App {
def matchTest(x: Int) = x match {
case 1 => "one"
case 2 => "two"
case _ if x > 9 && x < 100 => "兩位數" //支援條件表示式 這被稱為模式守衛
case _ => "other"
}
println(matchTest(1)) //輸出 one
println(matchTest(10)) //輸出 兩位數
println(matchTest(200 )) //輸出 other
}
複製程式碼
1.2 用作型別檢查
object ScalaApp extends App {
def matchTest[T](x: T) = x match {
case x: Int => "數值型"
case x: String => "字元型"
case x: Float => "浮點型"
case _ => "other"
}
println(matchTest(1)) //輸出 數值型
println(matchTest(10.3f)) //輸出 浮點型
println(matchTest("str" )) //輸出 字元型
println(matchTest(2.1)) //輸出 other
}
複製程式碼
1.3 匹配資料結構
匹配元組示例:
object ScalaApp extends App {
def matchTest(x: Any) = x match {
case (0,_,_) => "匹配第一個元素為 0 的元組"
case (a,b,c) => println(a + "~" + b + "~" + c)
case _ => "other"
}
println(matchTest((0,1,2))) // 輸出: 匹配第一個元素為 0 的元組
matchTest((1,2,3)) // 輸出: 1~2~3
println(matchTest(Array(10,11,12,14))) // 輸出: other
}
複製程式碼
匹配陣列示例:
object ScalaApp extends App {
def matchTest[T](x: Array[T]) = x match {
case Array(0) => "匹配只有一個元素 0 的陣列"
case Array(a,b) => println(a + "~" + b)
case Array(10,_*) => "第一個元素為 10 的陣列"
case _ => "other"
}
println(matchTest(Array(0))) // 輸出: 匹配只有一個元素 0 的陣列
matchTest(Array(1,2)) // 輸出: 1~2
println(matchTest(Array(10,12))) // 輸出: 第一個元素為 10 的陣列
println(matchTest(Array(3,1))) // 輸出: other
}
複製程式碼
1.4 提取器
陣列、列表和元組能使用模式匹配,都是依靠提取器 (extractor) 機制,它們伴生物件中定義了 unapply
或 unapplySeq
方法:
- unapply:用於提取固定數量的物件;
- unapplySeq:用於提取一個序列;
這裡以陣列為例,Array.scala
定義了 unapplySeq
方法:
def unapplySeq[T](x : scala.Array[T]) : scala.Option[scala.IndexedSeq[T]] = { /* compiled code */ }
複製程式碼
unapplySeq
返回一個序列,包含陣列中的所有值,這樣在模式匹配時,才能知道對應位置上的值。
二、樣例類
2.1 樣例類
樣例類是一種的特殊的類,它們被經過優化以用於模式匹配,樣例類的宣告比較簡單,只需要在 class
前面加上關鍵字 case
。下面給出一個樣例類及其用於模式匹配的示例:
//宣告一個抽象類
abstract class Person{}
複製程式碼
// 樣例類 Employee
case class Employee(name: String,age: Int,salary: Double) extends Person {}
複製程式碼
// 樣例類 Student
case class Student(name: String,age: Int) extends Person {}
複製程式碼
當你宣告樣例類後,編譯器自動進行以下配置:
- 構造器中每個引數都預設為
val
; - 自動地生成
equals,hashCode,toString,copy
等方法; - 伴生物件中自動生成
apply
方法,使得可以不用 new 關鍵字就能構造出相應的物件; - 伴生物件中自動生成
unapply
方法,以支援模式匹配。
除了上面的特徵外,樣例類和其他類相同,可以任意新增方法和欄位,擴充套件它們。
2.3 用於模式匹配
樣例的伴生物件中自動生成 unapply
方法,所以樣例類可以支援模式匹配,使用如下:
object ScalaApp extends App {
def matchTest(person: Person) = person match {
case Student(name,_) => "student:" + name
case Employee(_,salary) => "employee salary:" + salary
case _ => "other"
}
println(matchTest(Student("heibai",12))) //輸出: student:heibai
println(matchTest(Employee("ying",22,999999))) //輸出: employee salary:999999.0
}
複製程式碼
參考資料
- Martin Odersky . Scala 程式設計 (第 3 版)[M] . 電子工業出版社 . 2018-1-1
- 凱.S.霍斯特曼 . 快學 Scala(第 2 版)[M] . 電子工業出版社 . 2017-7
更多大資料系列文章可以參見 GitHub 開源專案: 大資料入門指南