1. 程式人生 > >【圖文詳細 】Scala——模式匹配

【圖文詳細 】Scala——模式匹配

5、Scala 的模式匹配 

Scala 有一個十分強大的模式匹配機制,可以應用到很多場合:如 switch 語句、型別檢查等。

並且 Scala 還提供了樣例類,對模式匹配進行了優化,可以快速進行匹配 
 

5.1、匹配字串

object CaseDemo01 extends App{
   val arr = Array("huangbo", "xuzheng", "wangbaoqiang","xxxx")
   val name = arr(Random.nextInt(arr.length)) 
 // name模式匹配字串 
  name match {
     case "huangbo" => println("影帝來也...")
     case "xuzheng" => println("喜劇笑星來了...")
     case "wangbaoqiang" => println("實力干將來也...")
     case _ => println("誰...???")
   }
 } 

 

5.2、匹配型別 

object CaseDemo02 extends App{ 
  //val v = if(x >= 5) 1 else if(x < 2) 2.0 else "hello" 
  val arr = Array("hello", 1, 2.0, CaseDemo) 
  val v = arr(Random.nextInt(4)) 
  println(v) 
 
  // 模式匹配
   v match { 
    case x: Int => println("Int " + x) 
    case y: Double if(y >= 0) => println("Double "+ y) 
    case z: String => println("String " + z) 
    case _ => throw new Exception("not match exception") 
  } 
} 
 
case class CaseDemo() 

注意:case y: Double if(y >= 0) => ... 模式匹配的時候還可以新增守衛條件。如不符合守衛條件,將掉入 case _中 

 

5.3、匹配陣列、元組、集合

object CaseDemo03 extends App{ 
 
  val arr = Array(1, 3, 5) 
  arr match { 
    case Array(1, x, y) => println(x + " " + y) 
    case Array(0) => println("only 0") 
    case Array(0, _*) => println("0 ...") 
    case _ => println("something else") 
  } 
 
  val lst = List(3, -1) 
  lst match { 
    case 0 :: Nil => println("only 0") 
    case x :: y :: Nil => println(s"x: $x y: $y") 
    case 0 :: tail => println("0 ...") 
    case _ => println("something else") 
  } 
 
  val tup = (2, 3, 7) 
  tup match { 
    case (1, x, y) => println(s"1, $x , $y") 
    case (_, z, 5) => println(z) 
    case  _ => println("else") 
  } 
}

注意:在 Scala 中列表要麼為空(Nil 表示空列表)要麼是一個 head 元素加上一個 tail 列表。

9 :: List(5, 2)  :: 操作符是將給定的頭和尾建立一個新的列表

注意::: 操作符是右結合的,如 9 :: 5 :: 2 :: Nil 相當於 9 :: (5 :: (2 :: Nil)) 

 

5.4、樣例類 
在 Scala 中樣例類是一中特殊的類,可用於模式匹配。

case class 是多例的,後面要跟構造引數,case object 是單例的 

object CaseDemo04 extends App{ 
 
  val arr = Array(CheckTimeOutTask, HeartBeat(123), SubmitTask("0001", "task1")) 
 
  arr(Random.nextInt(arr.length)) match { 
    case SubmitTask(id, name) => { 
      println(s"$id, $name") 
    } 
    case HeartBeat(time) => { 
      println(time) 
    } 
    case CheckTimeOutTask => { 
      println("check") 
    } 
  } 
} 
 
case class SubmitTask(id: String, name: String) 
case class HeartBeat(time: Long) 
case object CheckTimeOutTask 

當一個類被聲名為 case class 的時候,scala 會幫助我們做下面幾件事情:

1、構造器中的引數如果不被宣告為 var 的話,它預設的話是 val 型別的,但一般不推薦將 構造器中的引數宣告為 var

2、自動建立伴生物件,同時在裡面給我們實現子 apply 方法,使得我們在使用的時候可以 不直接顯示地 new 物件

3、伴生物件中同樣會幫我們實現 unapply 方法,從而可以將 case class 應用於模式匹配 apply 方法接受引數返回物件,unapply 方法接收物件返回引數

4、實現自己的 toString、hashCode、copy、equals 方法

5、case class 主建構函式裡面沒有修飾符,預設的是 val

除此之此,case class 與其它普通的 scala 類沒有區別 

object UnapplyTest { 
 
  // 接收引數,返回物件, 一般用作工廠
   def apply(value: Double, unit: String): Currency = new Currency(value, unit) 
 
  // 接收物件,返回引數, 一般用於模式匹配 
 def unapply(currency: Currency): Option[(Double, String)] = { 
    if (currency == null){ 
      None 
    } 
    else{ 
      Some(currency.value, currency.unit) 
    } 
  } 
} 
 
class Currency(val value: Double, val unit: String) { 
}

 

5.5、Option 型別 

在 Scala 中 Option 型別樣例類用來表示可能存在或也可能不存在的值(Option 的子類有 Some 和 None)。

Some 包裝了某個值,None 表示沒有值

object OptionDemo { 
 
  def main(args: Array[String]) { 
 
    val map = Map("a" -> 1, "b" -> 2) 
    val v = map.get("b") match { 
      case Some(i) => i 
      case None => 0 
    } 
    println(v) 
 
    // 更好的方式
     val v1 = map.getOrElse("c", 0) 
    println(v1) 
  } 
}

 

5.6、偏函式 
被包在花括號內沒有 match 的一組 case 語句是一個偏函式,

它是 PartialFunction[A, B]的一 個例項,A 代表引數型別,B 代表返回值型別,常用作輸入模式匹配

object PartialFuncDemo  { 
  // 偏函式
 
  def func1: PartialFunction[String, Int] = { 
    case "one" => 1 
    case "two" => 2 
    case _ => -1 
  } 
  // 普通函式的 模式匹配 實現
 
  def func2(num: String) : Int = num match { 
    case "one" => 1 
    case "two" => 2 
    case _ => -1 
  } 
 
  def main(args: Array[String]) { 
    println(func1("one")) 
    println(func2("one")) 
  } 
}

總結: 偏函式,就是用來做模式匹配的