常量模式與變量模式
- 功能類(lèi)似于其他語(yǔ)言的switch語(yǔ)句爵憎,但是在match case語(yǔ)句中是可以使用函數(shù)慨亲,也就意味著
- =>左側(cè)可以是任意的變量和條件表達(dá)式
- =>右側(cè)可以是任何復(fù)雜的函數(shù)
- 一旦匹配到就會(huì)執(zhí)行相應(yīng)的函數(shù)體并且返回結(jié)果
- 用法非常的自由,可以應(yīng)用在很多地方
- match case與if一樣是表達(dá)式宝鼓,而不是語(yǔ)句刑棵,可以直接賦值給一個(gè)變量
object Hello_Pattern_Match {
def main(args: Array[String]): Unit = {
//1
val data = 30
data match {
case 1 => println("First") //這是函數(shù)定義與實(shí)現(xiàn)的方式 =>左側(cè)可以是變量和條件表達(dá)式 =>右側(cè)可以是函數(shù)的實(shí)現(xiàn)
case 2 => println("Second")
case _ => println("Not know number") //case _ 代表所有的其它情況
} //row result:Not know number
//Scala中的模式匹配和Java中switch case相似
//其區(qū)別在于scala在每個(gè)匹配完成之后自動(dòng)break跳出不在往下匹配 等價(jià)于Java中的switch ... case : ... ; break;
//2
val result = data match {
case i if i == 1 => "The First" //i 和 number 為val 用于接收傳進(jìn)來(lái)的data 他們?cè)诼暶鞯臅r(shí)候會(huì)被實(shí)例化為data的內(nèi)容
case number if number == 2 => "Second"
case _ => "Not Know Number"
}
println("result="+result) //row result:Not know number
//3
"Spark !".foreach {
c => println(
c match {
case ' ' => "space"
case ch => "Char:" + ch
}
)
}
/**
* Char:S
Char:p
Char:a
Char:r
Char:k
space
Char:!
*/
}
}
Type、Array愚铡、List蛉签、Tuple模式匹配
object Pattern_Match_More {
def main(args: Array[String]): Unit = {
/**
* 通過(guò)模式匹配判斷參數(shù)的類(lèi)型
*/
def match_type(t: Any) = t match {
case p: Int => println("It is Integer") //這里的p變量 val p: Int t會(huì)賦值給變量p
case p: String => println("It is String, the content is " + p)
case m: Map[_, _] => m.foreach(println) //val m: Map[_, _]
case _ => println("Unknow type!!!")
}
match_type(2) //It is Integer
match_type("Spark") //It is String, the content is Spark
match_type(Map("Scala" -> "Spark")) //(Scala,Spark)
/**
* 模式匹配數(shù)組
*/
def match_array(arr: Any) = arr match {
case Array(0) => println("Array" + "0")
case Array(x, y) => println("Array" + x + " " + y) //匹配有兩個(gè)元素的數(shù)組
case Array(0, _*) => println("Array" + "0 ...") //匹配至少是1個(gè)元素,并且第一個(gè)元素為0的數(shù)組 _*表示后面有許多元素
case _ => println("something else")
}
match_array(Array(0)) //Array0
match_array(Array(0, 1)) //Array0 1
match_array(Array(0, 1, 2, 3, 4, 5, 6)) //Array0 ...
/**
* 模式匹配List
*/
def match_list(lst: Any) = lst match {
case 0 :: Nil => println("List" + "0") //匹配有一個(gè)元素的且為0的集合
case x :: y :: Nil => println("List" + x + " " + y) //匹配有兩個(gè)元素的集合
case 0 :: tail => println("List" + "0 ...") //x :: tail 表示開(kāi)頭的元素為0 tail表示剩下的若干個(gè)元素 匹配至少有一個(gè)元素的集合
case _ => println("something else")
}
match_list(List(0)) //List0
match_list(List(0, 1)) //List0 1
match_list(List(0, 1, 2, 3, 4, 5)) //List0 ...
/**
* 模式匹配Tuple元祖
*/
def match_tuple(tuple: Any) = tuple match {
case (0, _) => println("Tuple" + "0") //匹配第一個(gè)元素為0沥寥,第二個(gè)元素任意
case (x, 0) => println("Tuple:" + x)
case _ => println("something else")
}
match_tuple((0, "Scala")) //Tuple0
match_tuple((2, 0)) //Tuple:2
match_tuple((0, 1, 2, 3, 4, 5)) //something else
}
}
Scala提取器Extractor
- 提取器Extractor其實(shí)是調(diào)用了伴生對(duì)象中的unapply()方法
- unapplyf()方法其實(shí)就是apply()方法的反向操作碍舍,將構(gòu)造器中的參數(shù)拿出來(lái)
- scala中Array數(shù)組的模式匹配的原理就是用了unapply()方法
object ExtractorOps {
def main(args: Array[String]): Unit = {
def match_array(arr: Any) = arr match {
case Array(0) => println("Array" + "0")
case Array(x, y) => println("Array" + x + " " + y) //匹配有兩個(gè)元素的數(shù)組
case Array(0, _*) => println("Array" + "0 ...") //匹配至少是1個(gè)元素,并且第一個(gè)元素為0的數(shù)組 _*表示后面有許多元素
case _ => println("something else")
}
match_array(Array(0)) //Array0 //其實(shí)模式匹配在工作的時(shí)候會(huì)提取出0這個(gè)元素邑雅,拿到模式匹配中去比較片橡,這就是Extractor的作用
match_array(Array(0, 1)) //Array0 1 //同上...
match_array(Array(0, 1, 2, 3, 4, 5, 6)) //Array0 ...
//正則表達(dá)式匹配也是一個(gè)提取器
val pattern = "([0-9]+) ([a-z]+)".r
"20150626 hadoop" match {
case pattern(num, item) => println(num + ":" + item) //20150626:hadoop
}
}
}
case class
- 當(dāng)聲明樣例類(lèi)case class的時(shí)候內(nèi)部會(huì)自動(dòng)做的事情
- 構(gòu)造器中的每個(gè)參數(shù)成員都默認(rèn)聲明為val,也可以顯式的聲明var(不建議這樣做)
- 每個(gè)class都會(huì)有對(duì)應(yīng)的伴生對(duì)象淮野,在伴生對(duì)象中提供有apply方法捧书,讓我們不用new關(guān)鍵字就能夠構(gòu)造出相應(yīng)的對(duì)象
- 在模式匹配的時(shí)候非常重要的是吹泡,我們定義要從case class這個(gè)對(duì)象中提取出內(nèi)容,提取的方法也是在伴生對(duì)象里面unapply经瓷,unapply其實(shí)是apply的反操作
- 并且提供unapply方法讓模式匹配可以工作
- apply是傳遞值構(gòu)建對(duì)象爆哑,unapply是從已經(jīng)構(gòu)建的對(duì)象中提取內(nèi)容
- 也會(huì)自動(dòng)生成一些方法,例如:copy舆吮、toString揭朝、equals、hashCode
- 樣例類(lèi)和其他類(lèi)完全一樣色冀,你可以添加方法和字段萝勤,擴(kuò)展它們,等等
- spark中的worker工作節(jié)點(diǎn)和master節(jié)點(diǎn)通信的時(shí)候呐伞,他們就是傳遞case class和case object,因?yàn)樗麄兡J(rèn)情況下成員的內(nèi)容是不能修改的慎式,特別適合消息傳遞
- 當(dāng)接受消息后可以進(jìn)行模式匹配伶氢,然后進(jìn)行相應(yīng)的業(yè)務(wù)處理(讀取當(dāng)前worker的資源狀況)
abstract class Person //抽象類(lèi)
case class Student(age: Int) extends Person
case class Worker(age: Int, salary: Double) extends Person //樣例類(lèi)
case object Shared extends Person //單例的樣例對(duì)象
object Case_Class_Object {
def main(args: Array[String]): Unit = {
def caseOps(person: Person) = person match { //匹配的時(shí)候:樣例類(lèi)的實(shí)例使用(),樣例對(duì)象不使用圓括號(hào)
case Student(age) => println("I am " + age + "years old")
case Worker(_, salary) => println("Wow, I got " + salary)
case Shared => println("No property")
}
//Student這樣的定義方式其實(shí)是調(diào)用了apply方法
caseOps(Student(19)) //I am 19years old
caseOps(Shared) //No property
val worker = Worker(29, 10000.1)
val worker2 = worker.copy(salary = 19.95) //case class有一個(gè)copy的方法可以拷貝上一次的值
val worker3 = worker.copy(age = 30)
}
}
嵌套的Case class
- 樣例類(lèi)經(jīng)常被用于嵌套結(jié)構(gòu)
- 例如:某個(gè)商品售賣(mài)的物品瘪吏。有時(shí)候我們會(huì)將物品捆綁在一起打折銷(xiāo)售
abstract class Item
case class Book(description: String, price: Double) extends Item
case class Bundle(description: String, price: Double, items: Item*) extends Item
object Pattern_Match_Case_Class_Nested {
def main(args: Array[String]): Unit = {
def caseclass_nested(person: Item) = person match {
//@表示法將嵌套的值綁到變量上面
//art 是為了提取整個(gè)Book對(duì)象 相當(dāng)于的取了個(gè)別名 將Book的case class作為一個(gè)引用
case Bundle(_, _, art@Book(_, _), rest@_*) => println(art.description + ":" + art.price)
//_* 表示匹配多個(gè) 可以有也可以沒(méi)有
case Bundle(_, _, Book(descr, _), _*) => println("The first description is " + descr)
case _ => println("Oops!")
}
caseclass_nested(
Bundle("1111 Special's", 30.0,
Book("Scala for the Spark Developer", 69.95),
Bundle("Hadoop", 40.0,
Book("Hive", 79.95),
Book("HBase", 32.95)
)
)) //row result: Scala for the Spark Developer:69.95
caseclass_nested(
Bundle(
"1212 Special's",35.0,
Book("Spark for the Impatient", 39.95)
)
) //row result: Spark for the Impatient:39.95
}
}