本节主要内容

  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. 上传txt文件编码格式判断(文本乱码解决方法)

    说明 通过ajax或者浏览上传文本文件,上传时候c#处理时候因为文本格式的创建不同,在获取内容时候会出现中文乱码. 解决方法 通过上传的文件流,判断文件的编码格式,在使用对应的编码格式获取文本内容 # ...

  2. Python3.4的Pillow库实现验证码图片

    转自 http://blog.csdn.net/bin381/article/details/41969493 from PIL import Image,ImageDraw, ImageFont, ...

  3. What is JSON

    JSON (JavaScript Object Notation)  是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON具有以下这些形式: 对象是一个无序的“‘名称/值’对” ...

  4. golang协程——通道channel阻塞

    新的一年开始了,不管今天以前发生了什么,向前看,就够了. 说到channel,就一定要说一说线程了.任何实际项目,无论大小,并发是必然存在的.并发的存在,就涉及到线程通信.在当下的开发语言中,线程通讯 ...

  5. iOS,Core Animation--负责视图的复合功能

    简介 UIKit API UIKit是一组Objective-C API,为线条图形.Quartz图像和颜色操作提供Objective-C 封装,并提供2D绘制.图像处理及用户接口级别的动画.    ...

  6. blender--(凹凸贴图)................https://jingyan.baidu.com/article/9f63fb917c4becc8400f0ea8.html

    在blender中直接绘制模型凹凸纹理细节 听语音 | 浏览:32 | 更新:2018-02-20 11:18 1 2 3 4 5 6 7 分步阅读 在blender中为了表现更多的模型细节,我们会常 ...

  7. 梦想CAD控件图层COM接口知识点

    梦想CAD控件图层COM接口知识点 一.新建图层 主要用到函数说明: _DMxDrawX::AddLayer 增加新的图层.详细说明如下: 参数 说明 BSTR pszName 图层名 c#中实现代码 ...

  8. RabbitMQ系列(一)--消息中间件MQ如何去选择

    MQ在项目中的应用很普遍,本人所在项目组使用的是ActiveMQ,但是后面介绍的RabbitMQ... 一.应用场景 1.异步处理 2.流量削峰.秒杀 3.日志处理,推荐kafka 4.应用解耦 二. ...

  9. 01Microsoft SQL Server

    Microsoft SQL Server Microsoft SQL Server 是Microsoft 公司推出的关系型数据库管理系统.具有使用方便可伸缩性好与相关软件集成程度高等优点,可跨越膝上型 ...

  10. Invalid character found in the request target.The valid characters are defined in RFC 7230 and RFC3986

    Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后,添加了对于http头的验证. 具体来说,就是添加了些规则去限制HTTP头的规范性 参考这里 具体来说: org.apache.tom ...