Scala中Case Class与匹配模式是怎么回事

一.匹配模式

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{
 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章