一、模式匹配

Scala 支持模式匹配机制,可以代替 swith 语句、执行类型检查、以及支持析构表达式等。

1.1 更好的swith

Scala 不支持 swith,可以使用模式匹配 match...case 语法代替。但是 match 语句与 Java 中的 switch 有以下三点不同:

  • Scala 中的 case 语句支持任何类型;而 Java 中 case 语句仅支持整型、枚举和字符串常量;
  • Scala 中每个分支语句后面不需要写 break,因为在 case 语句中 break 是隐含的,默认就有;
  • 在 Scala 中 match 语句是有返回值的,而 Java 中 switch 语句是没有返回值的。如下:
object ScalaApp extends App {

  def matchTest(x: Int) = x match {
    case 1 => "one"
    case 2 => "two"
    case _ if x > 9 && x < 100 => "两位数"   //支持条件表达式 这被称为模式守卫
    case _ => "other"
  }

  println(matchTest(1))   //输出 one
  println(matchTest(10))  //输出 两位数
  println(matchTest(200)) //输出 other
}

1.2 用作类型检查

object ScalaApp extends App {

  def matchTest[T](x: T) = x match {
    case x: Int => "数值型"
    case x: String => "字符型"
    case x: Float => "浮点型"
    case _ => "other"
  }

  println(matchTest(1))     //输出 数值型
  println(matchTest(10.3f)) //输出 浮点型
  println(matchTest("str")) //输出 字符型
  println(matchTest(2.1))   //输出 other
}

1.3 匹配数据结构

匹配元组示例:

object ScalaApp extends App {

  def matchTest(x: Any) = x match {
    case (0, _, _) => "匹配第一个元素为 0 的元组"
    case (a, b, c) => println(a + "~" + b + "~" + c)
    case _ => "other"
  }

  println(matchTest((0, 1, 2)))             // 输出: 匹配第一个元素为 0 的元组
  matchTest((1, 2, 3))                      // 输出: 1~2~3
  println(matchTest(Array(10, 11, 12, 14))) // 输出: other
}

匹配数组示例:

object ScalaApp extends App {

  def matchTest[T](x: Array[T]) = x match {
    case Array(0) => "匹配只有一个元素 0 的数组"
    case Array(a, b) => println(a + "~" + b)
    case Array(10, _*) => "第一个元素为 10 的数组"
    case _ => "other"
  }

  println(matchTest(Array(0)))          // 输出: 匹配只有一个元素 0 的数组
  matchTest(Array(1, 2))                // 输出: 1~2
  println(matchTest(Array(10, 11, 12))) // 输出: 第一个元素为 10 的数组
  println(matchTest(Array(3, 2, 1)))    // 输出: other
}

1.4 提取器

数组、列表和元组能使用模式匹配,都是依靠提取器 (extractor) 机制,它们伴生对象中定义了 unapplyunapplySeq 方法:

  • unapply:用于提取固定数量的对象;
  • unapplySeq:用于提取一个序列;

这里以数组为例,Array.scala 定义了 unapplySeq 方法:

def unapplySeq[T](x : scala.Array[T]) : scala.Option[scala.IndexedSeq[T]] = { /* compiled code */ }

unapplySeq 返回一个序列,包含数组中的所有值,这样在模式匹配时,才能知道对应位置上的值。

二、样例类

2.1 样例类

样例类是一种的特殊的类,它们被经过优化以用于模式匹配,样例类的声明比较简单,只需要在 class 前面加上关键字 case。下面给出一个样例类及其用于模式匹配的示例:

//声明一个抽象类
abstract class Person{}
// 样例类 Employee
case class Employee(name: String, age: Int, salary: Double) extends Person {}
// 样例类 Student
case class Student(name: String, age: Int) extends Person {}

当你声明样例类后,编译器自动进行以下配置:

  • 构造器中每个参数都默认为 val
  • 自动地生成 equals, hashCode, toString, copy 等方法;
  • 伴生对象中自动生成 apply 方法,使得可以不用 new 关键字就能构造出相应的对象;
  • 伴生对象中自动生成 unapply 方法,以支持模式匹配。

除了上面的特征外,样例类和其他类相同,可以任意添加方法和字段,扩展它们。

2.3 用于模式匹配

样例的伴生对象中自动生成 unapply 方法,所以样例类可以支持模式匹配,使用如下:

object ScalaApp extends App {

  def matchTest(person: Person) = person match {
    case Student(name, _) => "student:" + name
    case Employee(_, _, salary) => "employee salary:" + salary
    case _ => "other"
  }

  println(matchTest(Student("heibai", 12)))        //输出: student:heibai
  println(matchTest(Employee("ying", 22, 999999))) //输出: employee salary:999999.0
}

参考资料

  1. Martin Odersky . Scala 编程 (第 3 版)[M] . 电子工业出版社 . 2018-1-1
  2. 凯.S.霍斯特曼 . 快学 Scala(第 2 版)[M] . 电子工业出版社 . 2017-7

更多大数据系列文章可以参见 GitHub 开源项目大数据入门指南

Scala 系列(十一)—— 模式匹配的更多相关文章

  1. scala 系列文章汇总

    本文作为scala系列文章索引 本博客目录: case class 背后的秘密 以spark源码为参照分析模式匹配及种类 另外,本文还收录了几个作者认为比较好的博文或网站: scala 相关网址汇总 ...

  2. Scala 系列(七)—— 常用集合类型之 Map & Tuple

    一.映射(Map) 1.1 构造Map // 初始化一个空 map val scores01 = new HashMap[String, Int] // 从指定的值初始化 Map(方式一) val s ...

  3. SQL Server 2008空间数据应用系列十一:提取MapInfo地图数据中的空间数据解决方案

    原文:SQL Server 2008空间数据应用系列十一:提取MapInfo地图数据中的空间数据解决方案 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Serv ...

  4. java基础解析系列(十一)---equals、==和hashcode方法

    java基础解析系列(十一)---equals.==和hashcode方法 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系 ...

  5. 第74讲:从Spark源码的角度思考Scala中的模式匹配

    今天跟随王老师学习了从源码角度去分析scala中的模式匹配的功能.让我们看看源码中的这一段模式匹配: 从代码中我们可以看到,case RegisterWorker(id,workerHost,.... ...

  6. Scala 经典的模式匹配和尾递归

    Scala 经典的模式匹配和尾递归 package io import java.io.{BufferedWriter, File, FileWriter} import java.text.Simp ...

  7. (数据科学学习手札49)Scala中的模式匹配

    一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...

  8. Scala基础:模式匹配和样例类

    模式匹配 package com.zy.scala import scala.util.Random /** * 模式匹配 */ object CaseDemo { def main(args: Ar ...

  9. struts2官方 中文教程 系列十一:使用XML进行表单验证

    在本教程中,我们将讨论如何使用Struts 2的XML验证方法来验证表单字段中用户的输入.在前面的教程中,我们讨论了在Action类中使用validate方法验证用户的输入.使用单独的XML验证文件让 ...

  10. 爬虫系列(十一) 用requests和xpath爬取豆瓣电影评论

    这篇文章,我们继续利用 requests 和 xpath 爬取豆瓣电影的短评,下面还是先贴上效果图: 1.网页分析 (1)翻页 我们还是使用 Chrome 浏览器打开豆瓣电影中某一部电影的评论进行分析 ...

随机推荐

  1. Java集合学习(10):hashcode() 和 equals()方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

  2. LCD硬件原理

    想象一下,屏幕的后面有一个电子枪,电子枪位于某个像素的背后,然后向这个像素发射红绿蓝三原色,从而就可以组成任意一种颜色.简单的说,电子枪在像素的背后一边移动,一边向像素发射红绿蓝. 如果要编写出LCD ...

  3. 09-C#笔记-循环

    1. while 同 C++ 2. for 同 C++ 3. foreach,注意数组的定义 int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 ...

  4. Ant Design Pro 鉴权/ 权限管理

    https://pro.ant.design/docs/authority-management-cn ant-design-pro 1.0.0 V4 最近需要项目需要用扫码登录,因此就使用antd ...

  5. java 8 学习二(Lambda表达式)

    粗略的概括:lambda表达式主要用来实现“函数接口”中“唯一”的抽象方法用的. 他的特殊版有 方法引用,构造函数引用,用对应的接口实例接收即可. 可以把Lambda表达式理解为简洁地表示可传递的匿名 ...

  6. Angle Beats Gym - 102361A(计算几何)

    Angle Beats \[ Time Limit: 4000 ms \quad Memory Limit: 1048576 kB \] 题意 给出 \(n\) 个初始点以及 \(q\) 次询问,每次 ...

  7. pyhton2 and python3 生成随机数字、字母、符号字典(用于撞库测试/验证码等)

    本文介绍Python3中String模块ascii_letters和digits方法,其中ascii_letters是生成所有字母,从a-z和A-Z,digits是生成所有数字0-9.string.p ...

  8. selenium--页面元素是否可见和可操作

    判断元素是否可见 from selenium import webdriver import unittest class Test_Display(unittest.TestCase): def t ...

  9. django -- 模版语言之过滤器Filters和for循环

    前戏 在前面写的图书管理系统中,我们对模版语言应该已经不陌生了,使用{{ }}包裹起来的就是模版语言,只需要记住两种就可以了 {{ 变量名 }}            变量相关的 {% %}      ...

  10. 网络协议 4 - 交换机与 VLAN:拓扑结构

    上一次,我们通过宿舍联网打魔兽的需求,认识了如何通过物理层和链路层组建一个宿舍局域网.今天,让我们切换到稍微复杂点的场景,办公室.     在这个场景里,就不像在宿舍那样,搞几根网线,拉一拉,扯一扯就 ...