• Scala入门到精通——第十五节 Case Class与模式匹配(二)


    本节主要内容

    1. 模式匹配的类型
    2. for控制结构中的模式匹配
    3. option类型模式匹配

    1. 模式的类型

    1 常量模式

    object ConstantPattern{
      def main(args: Array[String]): Unit = {
        //注意,以下定义的是一个函数
        //函数的返回值利用的是模式匹配后的结果作为其返回值
        //还须要注意的是函数定义在main方法中
        //也即scala语言能够在一个函数中定义另外一个函数
        def patternShow(x:Any)=x match {
          case 5 => "five"
          case true=>"true"
          case "test"=>"String"
          case null=>"null"
          case Nil=>"empty list"
          case _  =>"Other constant"
        }    
        println(patternShow(5))
      }
    }

    2 变量模式

    object VariablePattern{
      def main(args: Array[String]): Unit = {
        def patternShow(x:Any)=x match {
          case 5 => "five"
          //全部不是值为5的都会匹配变量y
          //比如"xxx"。则函数的返回结果就是"xxx"
          case y => y
        }   
        println(patternShow("xxx"))
      }
    }

    3 构造器模式

    //构造器模式必须将类定义为case class
    case class Person(name:String,age:Int)
    object ConstructorPattern {
      def main(args: Array[String]): Unit = {
          val p=new Person("摇摆少年梦",27)
          def constructorPattern(p:Person)=p match {
            case Person(name,age) => "Person"
            case _ => "Other"
          }
      }
    }

    4 序列(Sequence)模式
    序列模式指的是像Array、List这种序列集合进行模式匹配

    
    object SequencePattern {
      def main(args: Array[String]): Unit = {
          val p=List("spark","hive","SparkSQL")
          def sequencePattern(p:List[String])=p match {
            //仅仅须要匹配第二个元素
            case List(_,second,_*) => second
            case _ => "Other"
          }
          println(sequencePattern(p))
      }
    }

    5 元组模式

    //匹配某个元组内容
    object TuplePattern {
      def main(args: Array[String]): Unit = {
          val t=("spark","hive","SparkSQL")
          def tuplePattern(t:Any)=t match {
            case (one,_,_) => one
            case _ => "Other"
          }
          println(tuplePattern(t))
      }
    }

    6 类型模式

    //匹配传入參数的类型
    object TypePattern {
      def main(args: Array[String]): Unit = {
    
          def tuplePattern(t:Any)=t match {
            case t:String=> "String"
            case t:Int => "Integer"
            case t:Double=>"Double"
          }
          println(tuplePattern(5.0))
      }
    }

    上述代码假设不用模式匹配的话,要实现同样的功能,能够通过下列代码实现:

    def tuplePattern2(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"
          }

    7 变量绑定模式

    object VariableBindingPattern {
      def main(args: Array[String]): Unit = {
           var t=List(List(1,2,3),List(2,3,4))      
           def variableBindingPattern(t:Any)= t match {
             //变量绑定,採用变量名(这里是e)
             //与@符号,假设后面的模式匹配成功。则将
             //总体匹配结果作为返回
             case List(_,e@List(_,_,_)) => e
             case _ => Nil
           }
    
           println(variableBindingPattern(t))
      }
    }
    //编译运行后的输出结果为  List(2, 3, 4)

    2. for控制结构中的模式匹配

    object PatternInForLoop {
      def main(args: Array[String]): Unit = {
        val m=Map("china"->"beijing","dwarf japan"->"tokyo","Aerican"->"DC Washington")
        //利用for循环对Map进行模式匹配输出。
        for((nation,capital)<-m)
          println(nation+": " +capital)
      }
    }

    正則表達式中的模式匹配:

    object RegexMatch {
      def main(args: Array[String]): Unit = {
        val ipRegex="(\d+)\.(\d+)\.(\d+)\.(\d+)".r
        for(ipRegex(one,two,three,four) <- ipRegex.findAllIn("192.168.1.1"))
        {
          println("IP子段1:"+one)
          println("IP子段2:"+two)
          println("IP子段3:"+three)
          println("IP子段4:"+four)
        }
      }
    }

    3. Option类型模式匹配

    在前面的课程内容中,我们以前提到过Option类型,Option类型有两个子类。各自是Some和None(单例对象),本小节将从模式匹配的角度对Option类进行又一次思考。

    以下给出的是Option类在scala语言中的类层次结构:
    这里写代码片

    Option类事实上是一个sealed class

    //Option类的部分源代码
    sealed abstract class Option[+A] extends Product with Serializable {
      self =>
    
      /** Returns true if the option is $none, false otherwise.
       */
      def isEmpty: Boolean
    
      /** Returns true if the option is an instance of $some, false otherwise.
       */
      def isDefined: Boolean = !isEmpty
    

    以下给出的各自是Some及None的源代码:

    /** Class `Some[A]` represents existing values of type
     *  `A`.
     *
     *  @author  Martin Odersky
     *  @version 1.0, 16/07/2003
     */
    final case class Some[+A](x: A) extends Option[A] {
      def isEmpty = false
      def get = x
    }
    
    
    /** This case object represents non-existent values.
     *
     *  @author  Martin Odersky
     *  @version 1.0, 16/07/2003
     */
    case object None extends Option[Nothing] {
      def isEmpty = true
      def get = throw new NoSuchElementException("None.get")
    }

    以下的代码演示了其怎样应用到模式匹配中:

    object OptionDemo extends App{
      val m=Map("hive"->2,"spark"->3,"Spark MLlib"->4)
    
      def mapPattern(t:String)=m.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,对于case class我们已经非常熟悉了。那case object它又是怎么样的呢?假设我们定义了以下类:

    //以下的类主要用于模拟Option,Some,None三个类或对象之间的关系
    sealed abstract class A
    case class B(name:String,age:Int) extends A
    case object CaseObject extends A{
    
    }
    

    上述代码编译后,生成的字节码文件例如以下:

     D:ScalaWorkspaceScalaChapter15incnscalaxtwy 的文件夹
    
    2015/08/01  21:26    <DIR>          .
    2015/08/01  21:26    <DIR>          ..
    2015/08/01  21:26               515 A.class
    2015/08/01  21:26             1,809 B$.class
    2015/08/01  21:26             4,320 B.class
    2015/08/01  21:26             1,722 CaseObject$.class
    2015/08/01  21:26             1,490 CaseObject.class

    单从编译后生成的类来看。它们之间似乎实现方式都一样,那究竟是什么样的呢?

    class A的反编译后的代码例如以下:

    D:ScalaWorkspaceScalaChapter15incnscalaxtwy>javap -private A.class
    Compiled from "CaseObject.scala"
    public abstract class cn.scala.xtwy.A {
      public cn.scala.xtwy.A();
    }

    case class B相应的字节码文件反编译后例如以下:

    D:ScalaWorkspaceScalaChapter15incnscalaxtwy>javap -private B.class
    Compiled from "CaseObject.scala"
    public class cn.scala.xtwy.B extends cn.scala.xtwy.A implements scala.Product,sc
    ala.Serializable {
      private final java.lang.String name;
      private final int age;
      public static scala.Function1<scala.Tuple2<java.lang.String, java.lang.Object>
    , cn.scala.xtwy.B> tupled();
      public static scala.Function1<java.lang.String, scala.Function1<java.lang.Obje
    ct, cn.scala.xtwy.B>> curried();
      public java.lang.String name();
      public int age();
      public cn.scala.xtwy.B copy(java.lang.String, int);
      public java.lang.String copy$default$1();
      public int copy$default$2();
      public java.lang.String productPrefix();
      public int productArity();
      public java.lang.Object productElement(int);
      public scala.collection.Iterator<java.lang.Object> productIterator();
      public boolean canEqual(java.lang.Object);
      public int hashCode();
      public java.lang.String toString();
      public boolean equals(java.lang.Object);
      public cn.scala.xtwy.B(java.lang.String, int);
    }
    
    
    //自己主动生成的伴生对像类
    public final class cn.scala.xtwy.B$ extends scala.runtime.AbstractFunction2<java
    .lang.String, java.lang.Object, cn.scala.xtwy.B> implements scala.Serializable {
    
      public static final cn.scala.xtwy.B$ MODULE$;
      public static {};
      public final java.lang.String toString();
      public cn.scala.xtwy.B apply(java.lang.String, int);
      public scala.Option<scala.Tuple2<java.lang.String, java.lang.Object>> unapply(
    cn.scala.xtwy.B);
      private java.lang.Object readResolve();
      public java.lang.Object apply(java.lang.Object, java.lang.Object);
      private cn.scala.xtwy.B$();
    }
    
    

    case object CaseObject相应的反编译后的内容:

    D:ScalaWorkspaceScalaChapter15incnscalaxtwy>javap -private CaseObject.cla
    ss
    Compiled from "CaseObject.scala"
    public final class cn.scala.xtwy.CaseObject {
      public static java.lang.String toString();
      public static int hashCode();
      public static boolean canEqual(java.lang.Object);
      public static scala.collection.Iterator<java.lang.Object> productIterator();
      public static java.lang.Object productElement(int);
      public static int productArity();
      public static java.lang.String productPrefix();
    }
    
    
    D:ScalaWorkspaceScalaChapter15incnscalaxtwy>javap -private CaseObject$.cl
    ass
    Compiled from "CaseObject.scala"
    public final class cn.scala.xtwy.CaseObject$ extends cn.scala.xtwy.A implements
    scala.Product,scala.Serializable {
      public static final cn.scala.xtwy.CaseObject$ MODULE$;
      public static {};
      public java.lang.String productPrefix();
      public int productArity();
      public java.lang.Object productElement(int);
      public scala.collection.Iterator<java.lang.Object> productIterator();
      public boolean canEqual(java.lang.Object);
      public int hashCode();
      public java.lang.String toString();
      private java.lang.Object readResolve();
      private cn.scala.xtwy.CaseObject$();
    }

    对照上述代码不难看出。case object与case class所不同的是。case object相应反编译后的CaseObject$.cl
    ass中不存在apply、unapply方法,这是由于None不须要创建对象及进行内容提取。从这个角度讲,它被定义为case object是十分合理的。

    加入公众微信号,能够了解很多其它最新Spark、Scala相关技术资讯
    这里写图片描写叙述

  • 相关阅读:
    使用 RMAN 同步数据库
    关于MongoDB分布式高可用集群实现
    Oracle排错总结
    Oracle中Restore和Recovery的区别
    linux下防火墙iptables原理及使用
    RHEL6.5上升级OpenSSH7.4p1
    awk中next以及getline用法示例
    Linux下Redis的安装和部署
    Mongodb集群搭建的三种方式
    天地图服务地址
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7112666.html
Copyright © 2020-2023  润新知