Scala模式匹配詳解

qq_2631218300發表於2020-10-22

模式匹配是Scala中非常有特色,非常強大的一種功能。模式匹配,其實*類似於Java中的swich case語法,即對一個值進行條件判斷,然後針對不同的條件,進行不同的處理。

但是Scala的模式匹配的功能比Java的swich case語法的功能要強大地多,Java的swich case語法只能對值進行匹配。但是Scala的模式匹配除了可以對值進行匹配之外,還可以對型別進行匹配、對Array和List的元素情況進行匹配、對case class進行匹配、甚至對有值或沒值(Option)進行匹配。

而且對於Spark來說,Scala的模式匹配功能也是極其重要的,在spark原始碼中大量地使用了模式匹配功能。因此為了更好地編寫Scala程式,並且更加通暢地看懂Spark的原始碼,學好模式匹配都是非常重要的。
1、模式匹配的基礎語法

//scala沒有java中的switch case語法,但是有更強大的match case語法,即型別匹配,類替代
//match case的語法如下:變數 match { case 值 => 程式碼 }。_代表不滿足以上所有情況的預設。當有一個case分支滿足了,就不會繼續向下匹配了
//match case語法最基本的應用,就是對變數的值進行模式匹配
//案例:成績評價
object demo1{
  def main(args: Array[String]):Unit={
    def studentScore(score:String):Unit={
      score match{
        case "a"=>println("優秀")
        case "b"=>println("良好")
        case "c"=>println("一般")
        case _=>println("繼續努力")
      //_代表其他
      }
    }
    studentScore("a")  //優秀
  }
}

在模式匹配中使用if守衛

//scala模式匹配可以在case的條件判斷後加上一個if,進行雙重過濾
object demo1{
  def main(args: Array[String]):Unit={
    def studentScore(name:String,score:String):Unit={
      score match{
        case "a"=>println("優秀")
        case "b"=>println("良好")
        case "c"=>println("一般")
        case _ if name=="xiong"=>println(name+"是個好孩子,加油")
        case _=>println("繼續努力")
      }
    }
    studentScore("xiong","d") //xiong是個好孩子,加油
  }
}

在模式匹配中進行變數賦值

//在進行case匹配值的時候,就只有這一個值(在這裡是score),對於_(下劃線)這種情況,即不滿足以上所有情況的時候,都會進行預設的處理,此時我們可以使用變數賦值的方法在處理語句中加入這個值
object demo1{
  def main(args: Array[String]):Unit={
    def studentScore(name:String,score:String):Unit={
      score match{
        case "a"=>println("優秀")
        case "b"=>println("良好")
        case "c"=>println("一般")
        case _ if name=="xiong"=>println(name+"是個好孩子,加油")
        case _score=>println(name+"要努力呀,你的成績才為"+_score) //變數賦值
      }
    }
    studentScore("zhangSan","d") //zhangSan要努力呀,你的成績才為d
  }
}

2、對型別進行模式匹配

//scala可以直接匹配型別,而不是值
//語法 case 變數:型別 => 程式碼 與上面有一些細微差別
//案例:異常處理
object demo1{
  def main(args: Array[String]):Unit={
    import java.io._
    def processException(e:Exception):Unit={
      e match{
        case e1:IllegalArgumentException=>println("you have illegal arguments ! exception is :"+e1)
        case e2:FileNotFoundException=>println("cannot find the file you need read or write ! exception is :"+e2)
        case e3:IOException=>println("you got an error while you were doing IO operation ! exception is :"+e3)
        case _:Exception=>println("cannot know which exception you have")
      }
    }
    processException(new IOException())
  }
}

3、對Array和List的元素進行模式匹配

//對Array進行模式匹配,分別可以匹配帶有指定元素的陣列、帶有指定個數的陣列、以某元素開頭的陣列
//對List進行模式匹配,與Array類似,但是需要使用List特有的::操作符

//案列:對朋友打招呼
object demo1{
  def main(args: Array[String]):Unit={
    def greeting(arr:Array[String]):Unit={
      arr match{
        case Array("Leo")=>println("Hi,Leo!") //匹配一個元素
        case Array(a,b,c)=>println("Hi,"+a+","+b+","+c) //匹配三個元素
        case Array("Leo",_*)=>println("Hi,Leo,please introduce your friends to me.") //匹配Leo開頭的陣列
        case _=>println("Hey,who are you?")
      }
    }
    greeting(Array("Leo")) //Hi,Leo!
    greeting(Array("Leo","Jack","Bob")) //Hi,Leo,Jack,Bob
    greeting(Array("Leo","Jack","Bob","Alice")) //Hi,Leo,please introduce your friends to me.
    greeting(Array("Jack","Bob","Alice","Leo")) //Hey,who are you?
  }
}

//List
object demo1{
  def main(args: Array[String]):Unit={
    def greeting(list: List[String]){
      list match{
        case "Leo"::Nil=>println("Hi,Leo!")
        case "a"::"b"::"c"::Nil=>println("Hi,"+a+","+b+","+c) 
        case "Leo"::tail=>println("Hi,Leo,please introduce your friends to me.")
        case _=>println("Hey,who are you?")
      }
    }
    greeting(List("Leo")) //Hi,Leo!
    greeting(List("Leo","Jack","Bob")) //Hi,Leo,Jack,Bob
    greeting(List("Leo","Jack","Bob","Alice")) //Hi,Leo,please introduce your friends to me.
    greeting(List("Jack","Bob","Alice","Leo")) //Hey,who are you?
  }
}

case class 與模式匹配

// Scala中提供了一種特殊的類,用case class進行宣告,中文也可以稱作樣例類。case class其實有點類似於Java中的JavaBean的概念。即只定義field,並且由Scala編譯時自動提供getter和setter方法,但是沒有method。
// case class的主建構函式接收的引數通常不需要使用var或val修飾,Scala自動就會使用val修飾(但是如果你自己使用var修飾,那麼還是會按照var來)
//  Scala自動為case class定義了伴生物件,也就是object,並且定義了apply()方法,該方法接收主建構函式中相同的引數,並返回case class物件

//案例:學校門禁
class Person
case class Teacher(name:String,subject:String) extends Person
case class Student(name:String,age:Int) extends Person
case class Worker(name:String,work:String) extends Person
case class Stranger() extends Person
object demo1{
  def main(args: Array[String]):Unit={
    def entranceGuard(p:Person):Unit={
      p match{
        case Teacher(name,subject)=>println(s"Hello,$name,your teach is $subject")
        case Student(name,age)=>println(s"Hello,$name,your age is $age")
        case Worker(name,work) if work=="cleanner"==>println(s"Hello,$name,your work is $work")
        case Worker(name,work)=>println(s"Hello,$name,your work is $work,you should leavl 1 to 2 hours")
        case Stranger()=>println("stranger,you should leave right now")
      }
    }
    entranceGuard(Worker("Bob","cleanner"))
  }
}

Option與模式匹配

//Scala有一種特殊的型別,叫做Option。Option有兩種值,一種是Some,表示有值,一種是None,表示沒有值。
// Option通常會用於模式匹配中,用於判斷某個變數是有值還是沒有值,這比null來的更加簡潔明瞭
// Option的用法必須掌握,因為Spark原始碼中大量地使用了Option,比如Some(a)、None這種語法,因此必須看得懂Option模式匹配,才能夠讀懂spark原始碼。

//案例:成績評價
object demo1{
  def main(args: Array[String]):Unit={
    val grades=Map("Leo"->"a","Jack"->"b","Jen"->"c")
    def getGrade(name:String){
      val grade=grades.get(name)
      grade match{
        case Some(grade)=>println("your grade is "+grade)
        case None=>println("Sorry, your grade is not in this system")
      }
    }
    getGrade("Leo") //your grade is a
    getGrade("J") // Sorry, your grade is not in this system
  }
}

相關文章