Scala入门到精通——第十五节 Case Class与模式匹配(二)
本节主要内容
- 模式匹配的类型
- for控制结构中的模式匹配
- 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与模式匹配(二)的更多相关文章
- Scala入门到精通——第二十四节 高级类型 (三)
作者:摆摆少年梦 视频地址:http://blog.csdn.net/wsscy2004/article/details/38440247 本节主要内容 Type Specialization Man ...
- Scala入门到精通——第十六节 泛型与注解
本节主要内容 泛型(Generic Type)简单介绍 注解(Annotation)简单介绍 注解经常使用场景 1. 泛型(Generic Type)简单介绍 泛型用于指定方法或类能够接受随意类型參数 ...
- Scala入门到精通——第二十九节 Scala数据库编程
本节主要内容 Scala Mavenproject的创建 Scala JDBC方式訪问MySQL Slick简单介绍 Slick数据库编程实战 SQL与Slick相互转换 本课程在多数内容是在官方教程 ...
- Scala入门到精通——第十九节 隐式转换与隐式參数(二)
作者:摇摆少年梦 配套视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 隐式參数中的隐式转换 函数中隐式參数使用概要 隐式转换问题梳理 1. 隐式參数中的 ...
- Swift从入门到精通第十五篇 - 类型转换 初识
类型转换(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 类型转换 类型转换是检查实例类型的一种方法,或者检查来自类层级不同的父类或子类一个实例,用 is 和 as 操作符 为类 ...
- Simulink仿真入门到精通(十五) Simulink在流程工业中的仿真应用
15.1 工业乙醇生产与计算机仿真 乙醇作为可再生清洁能源不仅可以代替四乙基铅作为汽油的防爆剂,还可以制造汽油醇.这一巨大的潜在需求促使人们去寻找提高乙醇工业生产率的途径,使人们着手于发酵工程的研究. ...
- Scala入门到精通
原文出自于: http://my.csdn.net/lovehuangjiaju 感谢! 也感谢,http://m.blog.csdn.net/article/details?id=52233484 ...
- Simulink仿真入门到精通(十九) 总结回顾&自我练习
从2019年12月27到2020年2月12日,学习了Simulink仿真及代码生成技术入门到精通,历时17天. 学习的比较粗糙,有一些地方还没理解透彻,全书梳理总结: Simulink的基础模块已基本 ...
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
随机推荐
- 调度kettle使用taskctl我该怎么部署
转载自: http://www.taskctl.com/forum/detail_133.html 最近在QQ群看到有小伙伴在问用taskctl调度kettle,都要安装些什么呢?都支持哪些平台上的k ...
- golang tar gzip 压缩,解压(含目录文件)
tar是用于文件归档,gzip用于压缩.仅仅用tar的话,达不到压缩的目的.我们常见的tar.gz就是用gzip压缩生成的tar归档文件. go实现tar压缩与解压与zip类似,区别在于tar需要使用 ...
- Jenkins系列之Jenkins的工具配置和插件(二)
上一篇我们介绍了Jenkins的安装,这一篇我们介绍如何配置Jenkins的工具和如何下载插件. 首先我们先来看如何配置工具,这里的工具是指JDK.Ant.Maven.Git等. 一.如图,点击系统管 ...
- 梦想MxWeb3D,三维CAD协同设计平台 2019.04.09更新
SDK开发包下载地址: http://www.mxdraw.com/ndetail_10140.html 在线演示网址: http://www.mxdraw.com:3000/ 1. 增加上传dwg ...
- ThinkPHP---thinkphp文件加载
[一]文件加载在ThinkPHP里提供了三种方式 实际开发里,文件加载方式一般以第一种为主(通过函数库形式自动加载,此时我们仅仅需要定义文件和函数) (1)函数库形式加载 函数库分3种级别,系统函数库 ...
- PHP下载压缩包文件
PHP 压缩文件需要用到 ZipArchive 类,Windows 环境需要打开 php_zip.dll扩展. 压缩文件 $zip = new ZipArchive(); // 打开一个zip文档,Z ...
- luogu P3899 [湖南集训]谈笑风生 线段树合并
Code: #include<bits/stdc++.h> #define maxn 300002 #define ll long long using namespace std; vo ...
- Python isalpha() 方法检测字符串是否只由字母组成。
Python isalpha() 方法检测字符串是否只由字母组成.
- C: 字符数组中的空去掉
#include <stdio.h> #include <string.h> int main() { char a[50] = "nearby! "; i ...
- Go:字符串操作
Package strings:https://golang.google.cn/pkg/strings/ package main import ( "fmt" "st ...