一.匹配模式
Scala中匹配模式,類似與Java中的Switch。不過,Scala中匹配模式避免了Java Switch忘記Break時,穿透的問題。
演示如下:
for(i <- 1 to 100){
i match{
case 10 => println(10)
case 50 => println(50)
case 100 => println(100)
//增加條件
case _ if(i % 4 == 0) => println(i + ":能被4整除")
case _ if(i % 3 == 0) => println(i + ":能被3整除")
case _ =>
}
}
二.Case Class
1. Case Class使用
object caseTest {
def main(args: Array[String]): Unit = {
val p:Person = Student("Tom",22,80)
p match{
case Student(name,age,sno) => println("this is a student!")
case Teacher(name,age,tno) => println("this is a teacher!")
case Nobody(name) => println("unknown:"+name)
}
}
}
abstract class Person
case class Student(name:String,age:Int,sno:Int) extends Person
case class Teacher(name:String,age:Int,tno:Int) extends Person
case class Nobody(name:String) extends Person
Case Class總結
構造器的參數如果不被聲明爲var,默認是val
自動創建伴生對象同時實現apply方法,使得我們不必須new對象
伴生對象中同樣實現unapply方法,將case class應用於模式匹配
實現自己的toString、hashCode、copy、equals方法
除此之外,與普通class沒有區別
2.Case Class常用方法
object caseTest {
def main(args: Array[String]): Unit = {
val t = Teacher("James",34,1)
//無參copy方法
val t1 = t.copy()
println(t eq t1) //比較引用,false;深度拷貝
println(t == t1) //比較內容,true
println(t.equals(t1)) //比較內容,true
//帶一個參數的copy方法
println(t1.copy(name = "Kobe"))
//帶二個參數的copy方法
println(t1.copy(name = "Kobe",age = 22))
//帶三個參數的copy方法
println(t1.copy(name = "Kobe",age = 22,tno = 2))
//hashCode方法
println(t1.hashCode())
//toString方法
println(t1.toString())
}
}
abstract class Person
case class Student(name:String,age:Int,sno:Int) extends Person
case class Teacher(name:String,age:Int,tno:Int) extends Person
case class Nobody(name:String) extends Person
3.多參數Case Class
object caseTest {
def main(args: Array[String]): Unit = {
val sc = School("好好學習!",Teacher("Jordan",40,1),Student("Kobe",22,2))
sc match{
case School(_,_,Student(name,age,sno)) => println(name)
case _ => println("Nobody")
}
}
}
abstract class Person
case class Student(name:String,age:Int,sno:Int) extends Person
case class Teacher(name:String,age:Int,tno:Int) extends Person
case class Nobody(name:String) extends Person
//School爲接受多個Person類型參數的類
case class School(desc:String,persons:Person*)
4.sealed case class
有時候進行模式匹配,需要確保所有可能情況都列出,此時常常將它的超類定義爲sealed(密封的)case class。
object caseTest {
def main(args: Array[String]): Unit = {
val s:Person = Student("Lily",19,3)
//編譯器會提示:只匹配到了Student
//match may not be exhaustive.
//It would fail on the following inputs: Nobody(_), Teacher(_, _, _)
s match{
case Student(name,age,sno) => println("this is student!")
}
//下面語句才達到sealed case class的要求
s match{
case Student(name,age,sno) => println("this is student!")
case Teacher(name,age,tno) => println("this is teacher!")
case Nobody(name) => println("Nobody")
}
}
}
//Person最前面加了個關鍵字sealed
sealed abstract class Person
case class Student(name:String,age:Int,sno:Int) extends Person
case class Teacher(name:String,age:Int,tno:Int) extends Person
case class Nobody(name:String) extends Person
三.匹配模式
object caseTest {
def main(args: Array[String]): Unit = {
//1.常量模式與變量模式
def patternShow(x:Any) = x match{
//常量模式
case 1 => "one"
case true => "true"
case "str" => "string"
case null => "null"
case Nil => "empty list"
//變量模式
case y => y
}
println(patternShow(1))
//2.構造器模式
val p = new Person("James",33)
def conPattern(p:Person) = p match{
case Person(name,age) => "Person"
case _ => "Other"
}
//3.序列模式
//序列模式:類似Array、List這樣的序列集合進行模式匹配
val q = List("spark","hive","hadoop")
def seqPattern(q:List[String]) = q match{
//只需要匹配第二個元素
case List(_,second,_*) => second
case _ => "Other"
}
println(seqPattern(q))
//4.元組模式
//匹配某個元組內容
val t = ("spark","hive","hadoop")
def tuplePattern(t:Any) = t match{
case (one,_,_) => one
case _ => "other"
}
println(tuplePattern(t))
//5.類型模式
def typePattern(t:Any) = t match{
case t:String => "String"
case t:Int => "Integer"
case t:Double => "Double"
}
println(typePattern(50.3))
//等同於
def typePatternIf(t:Any) = {
if(t.isInstanceOf[String]) "String"
else if(t.isInstanceOf[Int]) "Int"
else if(t.isInstanceOf[Double]) "Double"
else if(t.isInstanceOf[Map[_,_]]) "MAP"
}
//6.變量綁定模式
val a = List(List(1,2,3),List(2,3,4))
def varBindPattern(t:Any) = t match{
//變量綁定,採用變量名(這裏使用e)與@符號。如果後面模式匹配成功,則將匹配結果返回
case List(_,e@List(_,_,_)) => e
case _ => Nil
}
println(varBindPattern(a))
}
}
//構造器模式必須將類定義爲case class
case class Person(name:String,age:Int)
四.For循環中的模式匹配
object caseTest1 {
def main(args: Array[String]): Unit = {
val map = Map("Jack" -> 100, "Lily" -> 93, "James" -> 90, "Robin" -> 87)
for ((name, score) <- map) {
println(name + "->" + score)
}
//正則匹配案例
val ip = "(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)".r
for (ip(one, two, three, four) <- ip.findAllIn("192.168.1.10")) {
println("IP子段1:" + one)
println("IP子段2:" + two)
println("IP子段3:" + three)
println("IP子段4:" + four)
}
}
}
五.Option類型模式匹配
Option類及其子類的源碼:
//Option類的部分源碼
sealed abstract class Option[+A] extends Product with Serializable {
self =>
def isEmpty: Boolean
def isDefined: Boolean = !isEmpty
}
//Some類的部分源碼
final case class Some[+A](x: A) extends Option[A] {
def isEmpty = false
def get = x
}
//None類的部分源碼
case object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
}
Option類型模式使用案例:
//Option是sealed class,它有兩個子類:Some、None(單例對象)。
val map = Map("hive"->2,"spark"->3,"Spark MLlib"->4)
def mapPattern(t:String) = map.get(t) match{
case Some(x) => println(x);x
case None => println("None");-1
}
println(mapPattern("Hive")) // None -1
None是一個Case Object,它同Some一樣都extends Option類,只不過Some是Case Class。接下來我們模擬一下這三個類之間的關係:
//下面的類主要用於模擬Option,Some,None三個類或對象之間的關係
sealed abstract class A
case class B(name:String,age:Int) extends A
case object CaseObject extends A{
}