一.匹配模式
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{
}