• Scala第十一章节(掌握模式匹配相关内容)


    1.模式匹配

    Scala中有一个非常强大的模式匹配机制,应用也非常广泛, 例如:

    • 判断固定值
    • 类型查询
    • 快速获取数据

    1.1 简单模式匹配

    一个模式匹配包含了一系列备选项,每个备选项都开始于关键字 case。且每个备选项都包含了一个模式及一到多

    表达式。箭头符号 => 隔开了模式和表达式。

    格式
    变量 match {
    case "常量1" => 表达式1
    case "常量2" => 表达式2
    case "常量3" => 表达式3
    case _ => 表达式4 // 默认匹配项
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    执行流程
    1. 先执行第一个case, 看 变量值 和 该case对应的常量值 是否一致.
    2. 如果一致, 则执行该case对应的表达式.
    3. 如果不一致, 则往后执行下一个case, 看 变量值 和 该case对应的常量值 是否一致.
    4. 以此类推, 如果所有的case都不匹配, 则执行 case _ 对应的表达式.
    需求
    1. 提示用户录入一个单词并接收.
    2. 判断该单词是否能够匹配以下单词,如果能匹配,返回一句话
    3. 打印结果.
    单词返回
    hadoop大数据分布式存储和计算框架
    zookeeper大数据分布式协调服务框架
    spark大数据分布式内存计算框架
    未匹配未匹配
    参考代码
    import scala.io.StdIn
    //案例: 模式匹配之简单匹配
    object ClassDemo01 {
    def main(args: Array[String]): Unit = {
    //1. 提示用户录入字符串并接收.
    println("请录入一个字符串: ")
    var str = StdIn.readLine()
    //2. 判断字符串是否是指定的内容, 并接收结果.
    val result = str match {
    case "hadoop" => "大数据分布式存储和计算框架"
    case "zookeeper" => "大数据分布式协调服务框架"
    case "spark" => "大数据分布式内存计算框架"
    case _ => "未匹配"
    }
    //3. 打印结果.
    println(result)
    println("-" * 15) //分割线.
    //简写形式
    str match {
    case "hadoop" => println("大数据分布式存储和计算框架")
    case "zookeeper" => println("大数据分布式协调服务框架")
    case "spark" => println("大数据分布式内存计算框架")
    case _ => println("未匹配")
    }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    1.2 匹配类型

    除了匹配数据之外, match表达式还可以进行类型匹配。如果我们要根据不同的数据类型,来执行不同的逻辑,也可以使用match表达式来实现。

    格式
    对象名 match {
    case 变量名1: 类型1 => 表达式1
    case 变量名2: 类型2 => 表达式2
    case 变量名3: 类型3 => 表达式3
    ...
    case _ => 表达式4
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意: 如果case表达式中无需使用到匹配到的变量,可以使用下划线代代

    需求
    1. 定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0
    2. 定义模式匹配,然后分别打印类型的名称
    参考代码
    //案例: 模式匹配之匹配类型
    object ClassDemo02 {
    def main(args: Array[String]): Unit = {
    //1. 定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0
    val a:Any = 1.0
    //2. 定义模式匹配,然后分别打印类型的名称
    val result = a match {
    case x:String => s"${x} 是String类型的数据"
    case x:Double => s"${x} 是Double类型的数据"
    case x:Int => s"${x} 是Int类型的数据"
    case _ => "未匹配"
    }
    //3. 打印结果
    println(result)
    //4. 优化版, 如果在case校验的时候, 变量没有被使用, 则可以用_替代.
    val result2 = a match {
    case _:String => "String"
    case _:Double => "Double"
    case _:Int => "Int"
    case _ => "未匹配"
    }
    //打印结果
    println(result2)
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    1.3 守卫

    所谓的守卫指的是 在case语句中添加if条件判断 , 这样可以让我们的代码更简洁, 更优雅.

    格式
    变量 match {
    case 变量名 if条件1 => 表达式1
    case 变量名 if条件2 => 表达式2
    case 变量名 if条件3 => 表达式3
    ...
    case _ => 表达式4
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    需求
    1. 从控制台读入一个数字a(使用StdIn.readInt)
    2. 如果 a >= 0 而且 a <= 3,打印[0-3]
    3. 如果 a >= 4 而且 a <= 8,打印[4,8]
    4. 否则,打印未匹配
    参考代码
    //案例: 模式匹配之守卫
    object ClassDemo03 {
    def main(args: Array[String]): Unit = {
    //1. 从控制台读入一个数字a(使用StdIn.readInt)
    println("请录入一个整数: ")
    var num = StdIn.readInt()
    //2. 模式匹配
    num match {
    //2.1 如果 a >= 0 而且 a <= 3,打印[0-3]
    case a if a >= 0 && a <= 3 => println("[0-3]")
    //2.2 如果 a >= 4 而且 a <= 8,打印[4,8]
    case a if a >= 4 && a <= 8 => println("[4-8]")
    //2.3 否则,打印未匹配
    case _ => println("未匹配")
    }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1.4 匹配样例类

    Scala中可以使用模式匹配来匹配样例类,从而实现可以快速获取样例类中的成员数据。后续,我们在开发Akka案

    例时,还会经常用到。

    格式
    对象名 match {
    case 样例类型1(字段1, 字段2, 字段n) => 表达式1
    case 样例类型2(字段1, 字段2, 字段n) => 表达式2
    case 样例类型3(字段1, 字段2, 字段n) => 表达式3
    ...
    case _ => 表达式4
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 样例类型后的小括号中, 编写的字段个数要和该样例类的字段个数保持一致.
    2. 通过match进行模式匹配的时候, 要匹配的对象必须声明为: Any类型.
    需求
    1. 创建两个样例类Customer(包含姓名, 年龄字段), Order(包含id字段)
    2. 分别定义两个样例类的对象,并指定为Any类型
    3. 使用模式匹配这两个对象,并分别打印它们的成员变量值
    参考代码
    //案例: 模式匹配之匹配样例类
    object ClassDemo04 {
    //1. 创建两个样例类Customer、Order
    //1.1 Customer包含姓名、年龄字段
    case class Customer(var name: String, var age: Int)
    //1.2 Order包含id字段
    case class Order(id: Int)
    def main(args: Array[String]): Unit = {
    //2. 分别定义两个案例类的对象,并指定为Any类型
    val c: Any = Customer("糖糖", 73)
    val o: Any = Order(123)
    val arr: Any = Array(0, 1)
    //3. 使用模式匹配这两个对象,并分别打印它们的成员变量值
    c match {
    case Customer(a, b) => println(s"Customer类型的对象, name=${a}, age=${b}")
    case Order(c) => println(s"Order类型, id=${c}")
    case _ => println("未匹配")
    }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    1.5 匹配集合

    除了上述功能之外, Scala中的模式匹配,还能用来匹配数组, 元组, 集合(列表, 集, 映射)等。

    1.5.1 示例一: 匹配数组
    需求
    1. 依次修改代码定义以下三个数
    Array(1,x,y) // 以1开头,后续的两个元素不固定
    Array(0) // 只匹配一个0元素的元素
    Array(0, ...) // 可以任意数量,但是以0开头
    
    • 1
    • 2
    • 3
    1. 使用模式匹配, 匹配上述数组.
    参考代码
    //案例: 模式匹配之匹配数组
    object ClassDemo05 {
    def main(args: Array[String]): Unit = {
    //1. 定义三个数组.
    val arr1 = Array(1, 2, 3)
    val arr2 = Array(0)
    val arr3 = Array(1, 2, 3, 4, 5)
    //2. 通过模式匹配, 找到指定的数组.
    arr2 match {
    //匹配: 长度为3, 首元素为1, 后两个元素无所谓.
    case Array(1, x, y) => println(s"匹配长度为3, 首元素为1, 后两个元素是: ${x}, ${y}")
    //匹配: 只有一个0元素的数组
    case Array(0) => println("匹配: 只有一个0元素的数组")
    //匹配: 第一个元素是1, 后边元素无所谓的数组.
    case Array(1, _*) => println("匹配: 第一个元素是1, 后边元素无所谓的数组")
    //其他校验项
    case _ => println("未匹配")
    }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1.5.2 示例二:匹配列表
    需求
    1. 依次修改代码定义以下三个列表
    List(0) // 只保存0一个元素的列表
    List(0,...) // 以0开头的列表,数量不固定
    List(x,y) // 只包含两个元素的列表
    
    • 1
    • 2
    • 3
    1. 使用模式匹配, 匹配上述列表.
    参考代码
    //案例: 模式匹配之匹配列表
    object ClassDemo06 {
    def main(args: Array[String]): Unit = {
    //1. 定义列表.
    var list1 = List(0)
    var list2 = List(0, 1, 2, 3, 4, 5)
    var list3 = List(1, 2)
    //2. 通过match进行模式匹配
    //思路一: 通过List()来实现.
    list1 match {
    case List(0) => println("匹配: 只有一个0元素的列表")
    case List(0, _*) => println("匹配: 0开头, 后边元素无所谓的列表")
    case List(x, y) => println(s"匹配: 只有两个元素的列表, 元素为: ${x}, ${y}")
    case _ => println("未匹配")
    }
    //思路二: 采用关键字优化 Nil, tail
    list1 match {
    case 0 :: Nil => println("匹配: 只有一个0元素的列表")
    case 0 :: tail => println("匹配: 0开头, 后边元素无所谓的列表")
    case x :: y :: Nil => println(s"匹配: 只有两个元素的列表, 元素为: ${x}, ${y}")
    case _ => println("未匹配")
    }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1.5.3 案例三:匹配元组
    需求
    1. 依次修改代码定义以下两个元组
    (1, x, y) // 以1开头的、一共三个元素的元组
    (x, y, 5) // 一共有三个元素,最后一个元素为5的元组
    
    • 1
    • 2
    1. 使用模式匹配, 匹配上述元组.
    参考代码
    //案例: 模式匹配之匹配元组
    object ClassDemo07 {
    def main(args: Array[String]): Unit = {
    //1. 定义两个元组.
    val a = (1, 2, 3)
    val b = (3, 4, 5)
    val c = (3, 4)
    //2. 通过模式匹配, 匹配指定的元素
    a match {
    case (1, x, y) => println(s"匹配: 长度为3,1开头, 后两个元素无所谓的元组, 这里后两个元素
    是: ${x}, ${y}")
    case (x, y, 5) => println(s"匹配: 长度为3,5结尾, 前两个元素无所谓的元素, 这里前两个元素
    是: ${x}, ${y}")
    case _ => println("未匹配")
    }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1.6 变量声明中的模式匹配

    在定义变量时,可以使用模式匹配快速获取数据. 例如: 快速从数组,列表中获取数据 .

    需求
    1. 生成包含0-10数字的数组,使用模式匹配分别获取第二个、第三个、第四个元素

    2. 生成包含0-10数字的列表,使用模式匹配分别获取第一个、第二个元素

    参考代码
    //案例: 演示变量声明中的模式匹配.
    object ClassDemo08 {
    def main(args: Array[String]): Unit = {
    //1. 生成包含0-10数字的数组,使用模式匹配分别获取第二个、第三个、第四个元素
    //1.1 生成包含0-10数字的数组
    val arr = (0 to 10).toArray
    //1.2 使用模式匹配分别获取第二个、第三个、第四个元素
    val Array(_, x, y, z, _*) = arr;
    //1.3 打印结果.
    println(x, y, z)
    println("-" * 15)
    //2. 生成包含0-10数字的列表,使用模式匹配分别获取第一个、第二个元素
    //2.1 生成包含0-10数字的列表,
    val list = (0 to 10).toList
    //2.2 使用模式匹配分别获取第一个、第二个元素
    //思路一: List() 实现
    val List(a, b, _*) = list
    //思路二: ::, tail 实现.
    val c :: d :: tail = list
    //2.3 打印结果.
    println(a, b)
    println(c, d)
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    1.7 匹配for表达式

    Scala中还可以使用模式匹配来匹配for表达式,从而实现快速获取指定数据, 让我们的代码看起来更简洁, 更优雅.

    需求
    1. 定义变量记录学生的姓名和年龄, 例如: “张三” -> 23, “李四” -> 24, “王五” -> 23, “赵六” -> 26
    2. 获取所有年龄为23的学生信息, 并打印结果.
    参考代码
    //案例: 模式匹配之匹配for表达式.
    object ClassDemo09 {
    def main(args: Array[String]): Unit = {
    //1. 定义变量记录学生的姓名和年龄.
    val map1 = Map("张三" -> 23, "李四" -> 24, "王五" -> 23, "赵六" -> 26)
    //2. 获取所有年龄为23的学生信息.
    //2.1 格式一: 通过if语句实现.
    for((k,v) <- map1 if v == 23) println(s"${k} = ${v}")
    //分割线.
    println("-" * 15)
    //2.2 格式二: 通过固定值实现.
    for((k, 23) <- map1) println(k + " = 23")
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    【2594. 修车的最少时间】
    C# 同步与异步方法
    DETR:End to End Object Detection with Transformers
    信息学奥赛一本通 1363:小球(drop)
    linux之后台运行命令
    Intel汇编-内联汇编改动的寄存器列表
    QEMU开发入门
    MISRA 2012学习笔记(5)-Rules 8.10
    PMP考试后多久出结果?(内附查成绩流程)
    《算法通关村—如何基于数组(或者链表)实现栈》
  • 原文地址:https://blog.csdn.net/m0_56525833/article/details/136882480