1. 程式人生 > >Scala - 07 - 模式匹配

Scala - 07 - 模式匹配

Scala中的模式匹配的功能可以應用到switch語句、型別檢查、“解構”等多種場合。

簡單匹配

Scala的模式匹配最常用於match語句中。Scala的match語句類似Java裡的switch。 匹配例項:
  def color(num: Int): String = {
    val colorNum = num
    val colorStr = colorNum match {
      case 1          => "red"
      case 2          => "green"
      case 3          => "yellow"
      //case _          => "Not Allowed"  //通配其他條件
      case unexpected => unexpected + " is Not Allowed" //可以在模式匹配的case語句中使用變數
    }
    s"$colorStr" //函式的返回值
  }                                               //> color: (num: Int)String

  color(1)                                        //> res0: String = red
  color(5)                                        //> res1: String = 5 is Not Allowed

型別模式

Scala可以對錶達式的型別進行匹配。
  for (elem <- List(9, 12.3, "Spark", "Hadoop", 'Hello)) {
    val str = elem match {
      case i: Int    => i + " is an int value."
      case d: Double => d + " is a double value."
      case "Spark"   => "Spark is found."
      case s: String => s + " is a string value."
      case _         => "This is an unexpected value."
    }
    println(str)
  }                                               //> 9 is an int value.
                                                  //| 12.3 is a double value.
                                                  //| Spark is found.
                                                  //| Hadoop is a string value.
                                                  //| This is an unexpected value.

"守衛(guard)"語句

在模式匹配中新增一些必要的處理邏輯。
  for (elem <- List(1, 2, 3, 4)) {
    elem match {
      case _ if (elem % 2 == 0) => println(elem + " is even.")
      case _                    => println(elem + " is odd.")
    }                                             //> 1 is odd.
                                                  //| 2 is even.
                                                  //| 3 is odd.
                                                  //| 4 is even.
  }

for表示式中的模式

迴圈遍歷對映的基本格式: for ((k,v) <- 對映) 語句塊 對映中的“鍵”被繫結到變數k上,對映中的“值”被繫結到變數v上。
  val test = Map(111 -> "AAA", "22" -> "BB", '3' -> 'c')
                                                  //> test  : scala.collection.immutable.Map[Any,Any] = Map(111 -> AAA, 22 -> BB, 3
                                                  //|  -> c)
  for ((k, v) <- test) printf("Key is : %s and value is: %s\n", k, v)
                                                  //> Key is : 111 and value is: AAA
                                                  //| Key is : 22 and value is: BB
                                                  //| Key is : 3 and value is: c

case類的匹配

case類是一種特殊的類,ke以被用於模式匹配。
  case class Car(brand: String, price: Int)
  val myBMWCar = new Car("BMW", 1200000)          //> myBMWCar  : TestScala.Car = Car(BMW,1200000)
  val myBenzCar = new Car("Benz", 1500000)        //> myBenzCar  : TestScala.Car = Car(Benz,1500000)
  for (car <- List(myBMWCar, myBenzCar)) {
    car match {
      case Car("BMW", 1200000) => println("Hello, BMW!")
      case Car(brand, price)   => println("Brand:" + brand + ", Price:" + price + ", do you want it?")
    }                                             //> Hello, BMW!
                                                  //| Brand:Benz, Price:1500000, do you want it?
  }

Option型別

一般而言,每種語言都會有一個關鍵字來表示一個物件引用的是“無”,在Java中使用的是null。 而在Scala中,如果變數或者函式返回值可能不會引用任何值的時候,建議使用Option型別。
  • Option類的子類Some,當存在可以被引用的值的時候,可以使用Some來包含這個值
  • None則被宣告為一個物件,而不是一個類,表示沒有值。
  • Option型別的getOrElse方法,可以在Option是Some的例項時返回對應的值,是None的例項時返回傳入的引數。
Option[T]型別
  • Option[T]型別中的T可以是Sting或Int或其他各種資料型別。
  • Option[T]實際是一個特殊的集合,要麼只包含一個元素(被包裝在Some中返回),要麼就不存在元素(返回None)。
  • 可以針對Option[T]使用map、foreach或者filter等集合的方法。
  val books = Map("AAA" -> 111, "BBB" -> 222, "CCC" -> 333)
                                                  //> books  : scala.collection.immutable.Map[String,Int] = Map(AAA -> 111, BBB ->
                                                  //|  222, CCC -> 333)
  books.get("AAA")                                //> res0: Option[Int] = Some(111)
  books.get("DDD")                                //> res1: Option[Int] = None

  val sales = books.get("BBB")                    //> sales  : Option[Int] = Some(222)
  books.get("BBB").getOrElse("No Such Book - BBB")//> res2: Any = 222

  books.get("DDD").getOrElse("No Such Book - DDD")//> res3: Any = No Such Book - DDD
  
  books.get("CCC").foreach(println)               //> 333
  books.get("DDD").foreach(println)

注意:

  books.get("AAA") //Key存在,取到的value值被包含在Some中返回   books.get("DDD") //key不存在,取到的值是None物件