本节主要内容

  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:\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$.cl

ass中不存在apply、unapply方法,这是由于None不须要创建对象及进行内容提取。从这个角度讲,它被定义为case object是十分合理的。

加入公众微信号,能够了解很多其它最新Spark、Scala相关技术资讯

Scala入门到精通——第十五节 Case Class与模式匹配(二)的更多相关文章

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

    作者:摆摆少年梦 视频地址:http://blog.csdn.net/wsscy2004/article/details/38440247 本节主要内容 Type Specialization Man ...

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

    本节主要内容 泛型(Generic Type)简单介绍 注解(Annotation)简单介绍 注解经常使用场景 1. 泛型(Generic Type)简单介绍 泛型用于指定方法或类能够接受随意类型參数 ...

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

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

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

    作者:摇摆少年梦 配套视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 隐式參数中的隐式转换 函数中隐式參数使用概要 隐式转换问题梳理 1. 隐式參数中的 ...

  5. Swift从入门到精通第十五篇 - 类型转换 初识

    类型转换(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 类型转换 类型转换是检查实例类型的一种方法,或者检查来自类层级不同的父类或子类一个实例,用 is 和 as 操作符 为类 ...

  6. Simulink仿真入门到精通(十五) Simulink在流程工业中的仿真应用

    15.1 工业乙醇生产与计算机仿真 乙醇作为可再生清洁能源不仅可以代替四乙基铅作为汽油的防爆剂,还可以制造汽油醇.这一巨大的潜在需求促使人们去寻找提高乙醇工业生产率的途径,使人们着手于发酵工程的研究. ...

  7. Scala入门到精通

    原文出自于: http://my.csdn.net/lovehuangjiaju 感谢! 也感谢,http://m.blog.csdn.net/article/details?id=52233484 ...

  8. Simulink仿真入门到精通(十九) 总结回顾&自我练习

    从2019年12月27到2020年2月12日,学习了Simulink仿真及代码生成技术入门到精通,历时17天. 学习的比较粗糙,有一些地方还没理解透彻,全书梳理总结: Simulink的基础模块已基本 ...

  9. Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G

    code&monkey   Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...

随机推荐

  1. VS2013使用单元测试

    一.开发环境 开发工具:VS2013 二.开发流程 1.添加一个控制台项目UnitDemo namespace UnitDemo { public class Program { static voi ...

  2. ubuntu系统中查看本机cpu和内存信息的命令和用法

    https://zhidao.baidu.com/question/192966322.html 写出ubuntu linux系统中查看本机cpu和内存信息的命令和用法,以及如何解读这些命令 ubun ...

  3. 华硕(ASUS)X554LP笔记本重装win7后网卡和USB驱动问题的解决

    以前在其它笔记本上采用U盘克隆安装winxp系统非常顺利,各种硬件驱动能自动识别并安装. 手上有一台别人的华硕(ASUS)X554LP笔记本,原装win8.1,用不惯,想装个win7旗舰版. 照例去系 ...

  4. OC语言Block

    OC语言Block 一.Block (一)简介  Block是什么?苹果推荐的比较特殊的数据类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. Block和 ...

  5. Acunetix Web Vulnerability Scanner使用和生成报告的方法

    Acunetix WVS,该扫描软件的全称Acunetix Web Vulnerability Scanner,是一个网站及服务器漏洞扫描软件.它可以检查Web应用程序中的漏洞,如SQL注入.跨站脚本 ...

  6. MySql (二)入门语句和基本操作

    mysql的入门语句:查看服务器下的库 show databases; 创建库(数据库被创建后它的名字是不可以更改的) create database 数据库名; 2.1.插看当前所在的库 selec ...

  7. acedssget

    大多数ObjectARX函数在处理选择集和实体时,都用名字来识别选择集或实体,该名字用一个长整型对来表示的,并对AutoCAD来维护.在ObjectARX中,该名字的类型为ads_name.在对选择集 ...

  8. 梦想CAD控件安卓交互绘图

    在cad使用过程中,动态绘制的使用会使我们绘图速度大大加快.在此演示中,我们绘制了直线.多段线.点.样条线.圆.圆弧.椭圆.椭圆弧等实体. 用户可以在CAD控件视区任意位置绘制直线. 主要用到函数说明 ...

  9. 梦想3D控件 2018.7.26更新

    下载地址: http://www.mxdraw.com/ndetail_108.html 1.  编写所有接口函数使用的CHM文档 2.  增加交互绘制功能 3.  增加案例弧形窗建模案例 4.  增 ...

  10. 第三节:执行一些EF的增删改查

    针对两表操作 一丶增加 #region 05-增加操作 /// <summary> /// 05-增加操作 /// </summary> /// <param name= ...