Scala模式匹配

541732025發表於2015-12-08
基本模式匹配:

點選(此處)摺疊或開啟

  1. def main(args: Array[String]) {
  2.     val data =2
  3.     data match {
  4.      case 1 => println("First") //類似於函式的定義與實現(case可以是變數,也可以是條件表示式
  5.      case 2 => println("Second") //不同於java,這裡不需要break關鍵字,匹配之後會自動返回
  6.      case _ => println("Not Known Number") //預設情況
  7.      }
  8.   
  9.     val result = data match { //match可以返回結果
  10.      case i if i == 1 => "The First" //val i常量,使用match時,data傳進來時就會賦值給i
  11.      case number if number ==2 => "The Second" + number //number的初始化同i,並且number在case語句,以及函式體中都可以被使用。
  12.      case _ => "Not Known Number"
  13.      }
  14.     println(result)
  15.          
  16.     "Spark !" foreach { c => println (
  17.      c match {
  18.      case ' ' => "space"
  19.      case ch => "Char: " + ch
  20.      }
  21.      )}
  22.     
  23.   }

Type模式匹配:

點選(此處)摺疊或開啟

  1. def match_type(t : Any) = t match {
  2.     case p : Int => println("It is Integer")
  3.     case p : String => println("It is String, the content is : " + p)
  4.     case m: Map[_, _] => m.foreach(println)
  5.     case _ => println("Unknown type!!!")
  6.     }
  7.     
  8.     match_type(2)
  9.     match_type("Spark")
  10.     match_type(Map("Scala" -> "Spark"))
結果:
It is Integer
It is String, the content is : Spark
(Scala,Spark)

Array模式匹配:

點選(此處)摺疊或開啟

  1. def match_array(arr : Any) = arr match {
  2.      case Array(0) => println("Array:" + "0")  //匹配Array只有1個元素,而且是0
  3.      case Array(x, y) => println("Array:" + x + " " +y) //匹配兩個元素
  4.      case Array(0, _*) => println("Array:" + "0 ...")  //匹配至少1個元素,而且第一個元素是0
  5.      case _ => println("something else")
  6.     }
  7.     
  8.     match_array(Array(0))
  9.     match_array(Array(1,2))
  10.     match_array(Array(0,1,2,3,4,5))
結果:
Array:0
Array:1 2
Array:0 ...

List模式匹配:

點選(此處)摺疊或開啟

  1. def match_list(lst : Any) = lst match {
  2.      case 0 :: Nil => println("List:" + "0") //匹配List只有一個元素,而且是0
  3.      case x :: y :: Nil => println("List:" + x + " " + y) //匹配List有兩個元素
  4.      case 0 :: tail => println("List:" + "0 ...") //匹配List至少有一個元素,而且第一個元素是0
  5.      case _ => println("something else")
  6.     }
  7.     
  8.     match_list(List(0))
  9.     match_list(List(3,4))
  10.     match_list(List(0,1,2,3,4,5))
結果:
List:0
List:3 4
List:0 ...

Tuple模式匹配:

點選(此處)摺疊或開啟

  1. def match_tuple(tuple : Any) = tuple match {
  2.     case (0, _) => println("Tuple:" + "0") //匹配第一個元素是0,第二個任意
  3.     case (x, 0) => println("Tuple:" + x ) //匹配第一個元素任意,第二個元素是0
  4.     case _ => println("something else")
  5.     }
  6.     
  7.     match_tuple((0,"Scala"))
  8.     match_tuple((2,0))
  9.     match_tuple((0,1,2,3,4,5))
結果:
Tuple:0
Tuple:2
something else

case class與case object模式匹配:

點選(此處)摺疊或開啟

  1. abstract class Person
  2. //每個case class都會有一個伴生物件,apply方法負責建立case class的例項
  3. case class Student(age: Int) extends Person //預設宣告為val,不可變
  4. case class Worker(age: Int, salary: Double) extends Person
  5. case object Shared extends Person

  6. object case_class_object {
  7.   def main(args: Array[String]){
  8.    
  9.     //面向介面(Persion)
  10.      def caseOps(person: Person) = person match {
  11.          case Student(age) => println("I am " + age + "years old") //從傳進來的person物件中析取age值,構造新的Student物件這個提取動作發生在伴生物件的unApply方法中
  12.          case Worker(_, salary) => println("Wow, I got " + salary)
  13.          case Shared => println("No property")
  14.          }
  15.      caseOps(Student(19))
  16.      caseOps(Shared)
  17.     
  18.     val worker = Worker(29, 10000.1) //apply呼叫
  19.     val worker2 = worker.copy(salary = 19.95) //複製一個新的物件,並且重新賦值
  20.     val worker3 = worker.copy(age = 30)
  21.   }
  22. }
用途:傳遞訊息與模式匹配,spark中worker與master進行通訊的時候,傳遞case class或者case object,接收訊息後再進行模式匹配

巢狀case class的模式匹配:

點選(此處)摺疊或開啟

  1. def main(args: Array[String]) {
  2.     def caseclass_nested(item: Item) = item match {
  3.       case Bundle(_, _, art @ Book(_, _), rest @ _*) => println(art.description + " : " + art.price) //使用@符號可以引用這個物件
  4.          case Bundle(_, _, Book(descr, _), _*) => println("The first description is :" + descr)
  5.          case _ => println("Oops!")
  6.          }
  7.      caseclass_nested(Bundle("1111 Special's", 30.0,
  8.      Book("Scala for the Spark Developer", 69.95),
  9.      Bundle("Hadoop", 40.0,
  10.      Book("Hive", 79.95),
  11.      Book("HBase", 32.95)
  12.      )
  13.      ))
  14.      caseclass_nested(Bundle("1212 Special's", 35.0,
  15.              Book("Spark for the Impatient", 39.95)
  16.              ))
  17.   }

Option的使用:

點選(此處)摺疊或開啟

  1. sealed abstract class Option[+A] extends Product with Serializable

點選(此處)摺疊或開啟

  1. final case class Some[+A](x: A) extends Option[A] {
  2.   def isEmpty = false
  3.   def get = x
  4. }

點選(此處)摺疊或開啟

  1. case object None extends Option[Nothing] {
  2.   def isEmpty = true
  3.   def get = throw new NoSuchElementException("None.get")
  4. }

sealed:強制要求,Option下定義的的case class(Some)或者case object(None)都必須在同一個檔案中。

點選(此處)摺疊或開啟

  1. def main(args: Array[String]){
  2.     val scores = Map("Alice" -> 99, "Spark" -> 100)
  3.     
  4.     scores.get("Spark") match { //Map的get方法返回Option型別的值
  5.      case Some(score) => println(score)
  6.      //或者這樣:
  7.      case a @ Some(score) => println(a.get)
  8.      case None => println("No score")
  9.     }
  10.   }

模式匹配下的for迴圈
object For_Advanced {
  def main(args: Array[String]): Unit = {
    for(i <- List(1,2,3,4,5) ) {println(i)}
    
    //變數繫結,給Flink設定別名,然後模式匹配值

    for(index@"Flink" <- List("Hadoop","Spark","Flink") ) {println(index)} //Flink
    
    //模式匹配具體的值

    for ((language,"Hadoop") <- Set("Scala"->"Spark","Java"->"Hadoop") ) println(language) //Java

    //模式匹配型別

    for((k,v:Int) <- List(("Spark"->5),("Hadoop"->"Big Data"))) {println(k)}
  }
}

模式匹配下的賦值語句

點選(此處)摺疊或開啟

  1. object Assinment_Internals {

  2.   def main(args: Array[String]) {
  3.     val a@b = 1000 //a是b別名,模式匹配後返回二元Tuple(a, b)
  4.     println("a = " + a + ", b = " + b)
  5.     val (c,d) = (1000,2000)
  6. // val (e,F) = (1000,2000) //F大寫的話會把它當成常量,而常量未定義則會報錯
  7.     val Array(g,h) = Array(1000,2000)
  8. // val Array(i,J) = Array(1000,2000)
  9. // object Test { val 1 = 1 } //看傳進來的值是否匹配1
  10.     object Test { val 1 = 2 } //編譯器lazy匹配,所以編譯透過,但是執行報錯
  11.   }
  12. }

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28912557/viewspace-1868605/,如需轉載,請註明出處,否則將追究法律責任。

相關文章