本节主要内容

  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"}}
}
  • 1

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,_*) => secondcase _ => "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,_,_) => onecase _ => "Other"}println(tuplePattern(t))}
}
  • 1

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(_,_,_)) => ecase _ => Nil}println(variableBindingPattern(t))}
}
//编译执行后的输出结果为  List(2, 3, 4)
  • 1

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+)".rfor(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 = falsedef 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 = truedef 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);xcase 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:\ScalaWorkspace\ScalaChapter15\bin\cn\scala\xtwy 的目录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:\ScalaWorkspace\ScalaChapter15\bin\cn\scala\xtwy>javap -private A.class
Compiled from "CaseObject.scala"
public abstract class cn.scala.xtwy.A {public cn.scala.xtwy.A();
}

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

D:\ScalaWorkspace\ScalaChapter15\bin\cn\scala\xtwy>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:\ScalaWorkspace\ScalaChapter15\bin\cn\scala\xtwy>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:\ScalaWorkspace\ScalaChapter15\bin\cn\scala\xtwy>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$.class中不存在apply、unapply方法,这是因为None不需要创建对象及进行内容提取,从这个角度讲,它被定义为case object是十分合理的。

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

  1. Scala入门到精通——第十四节 Case Class与模式匹配(一)

    本节主要内容 模式匹配入门 Case Class简介 Case Class进阶 1. 模式匹配入门 在Java语言中存在switch语句,例如: //下面的代码演示了java中switch语句的使用 ...

  2. Scala入门到精通——第二十五节 提取器(Extractor)

    本节主要内容 apply与unapply方法 零变量或变量的模式匹配 提取器与序列模式 scala中的占位符使用总结 1. apply与unapply方法 apply方法我们已经非常熟悉了,它帮助我们 ...

  3. Scala入门到精通——第二十六节 Scala并发编程基础

    本节主要内容 Scala并发编程简介 Scala Actor并发编程模型 react模型 Actor的几种状态 Actor深入使用解析 1. Scala并发编程简介 2003 年,Herb Sutte ...

  4. Scala入门到精通——第二十九节 Scala数据库编程

    本节主要内容 Scala Mavenproject的创建 Scala JDBC方式訪问MySQL Slick简单介绍 Slick数据库编程实战 SQL与Slick相互转换 本课程在多数内容是在官方教程 ...

  5. Scala入门到精通——第二十四节 高级类型 (三)

    本节主要内容 Type Specialization Manifest.TypeTag.ClassTag Scala类型系统总结 在Scala中,类(class)与类型(type)是两个不一样的概念. ...

  6. Scala入门到精通——第十九节 隐式转换与隐式参数(二)

    本节主要内容 隐式参数中的隐式转换 函数中隐式参数使用概要 隐式转换问题梳理 1. 隐式参数中的隐式转换 前一讲中,我们提到函数中如果存在隐式参数,在使用该函数的时候如果不给定对应的参数,则编译器会自 ...

  7. Scala入门到精通——第十六节 泛型与注解

    本节主要内容 泛型(Generic Type)简介 注解(Annotation)简介 注解常用场景 1. 泛型(Generic Type)简介 泛型用于指定方法或类可以接受任意类型参数,参数在实际使用 ...

  8. Excel数据分析从入门到精通(十五)数据透视表之动态仪表盘

    Excel数据分析从入门到精通(十五)数据透视表之动态仪表盘 1.绘制销售额汇总情况 2.绘制种类销售额情况+种类销售额占比 种类销售额情况 种类销售占比 3.绘制地区销售额情况和地区销售额占比 地区 ...

  9. Excel数据分析从入门到精通(十五)数据透视表基础

    Excel数据分析从入门到精通(十五)数据透视表 1.Excel透视表前言 2.Excel透视表的创建 3.Excel透视表的组成 4.Excel透视表的十大技巧 ①如何创建汇总行 ②如何展示百分比 ...

最新文章

  1. [BZOJ1572][Usaco2009 Open]工作安排Job
  2. 利用java多线程向MongoDB中批量插入静态文件
  3. Linux scp常用命令
  4. python打完代码怎么运行-Python的代码是如何去进行运行的?
  5. ubuntu16.04安装UR3/UR5/UR10机械臂的ROS驱动并实现gazebo下Moveit运动规划仿真以及真实UR3机械臂的运动控制(3)
  6. win phone 获取并且处理回车键事件
  7. Open3d之文件IO
  8. Prototype使用$R()函数
  9. css table中设置tr行间距
  10. 第三届泰迪杯全国大学生数据挖掘竞赛通知
  11. Arduino + W5100调试笔记(1)
  12. MOOC 哈工大苏小红C语言 第七周练兵区——编程题
  13. 数据处理常用方法(python)
  14. 搬砖的成长之路——VMWare网络原理
  15. 多台linux服务器ssh相互无密码访问
  16. CatBoost参数解释
  17. 移动桌面到其他盘:C盘不够用,如何【修改桌面存储位置】
  18. 《资本论》读书笔记(2)第二卷第一章:资本形态变化及其循环
  19. 对一阶二阶低通滤波器推导,并用IMU数据验证算法效果
  20. C++ 实现1011 A+B 和 C

热门文章

  1. (干货满满!)session和cookie作用原理,区别(史上最详细)
  2. yy直播没声音html,驱动技巧:解决YY语音中麦克风无声或者有噪音的问题
  3. 如何统一集体的所有人的yum环境(以阿里云为例)
  4. kotlin读取sd卡里的文件_Kotlin 读取文件
  5. unity3d 不规则外发光描边_Shader案例之内发光和边缘泛光效果
  6. java threadstatus_Thread之一:线程生命周期及六种状态
  7. php正则相对地址,php – 正则表达式将相对URL更改为绝对值
  8. php父类继承子类_php有多态吗 多态都有什么好处?理解好多态往往能事半功倍...
  9. mongodb启动成功连不上_MySQL数据导入到MongoDb教程
  10. php在html中生成option,php-如何为使用laravel表单生成器创建的select标签的选项指定HTML属性?...