• Scala入门到精通(尚硅谷学习笔记)章节十——模式匹配


    基本语法

    scala的模式匹配类似于Java中的swich case语法,对一个值进行条件判断,针对不同的条件,进行不同的处理。
    Scala的模式匹配除了可以对值进行匹配之外,还可以对类型、Array和List的元素情况case class、有值或没值(Option)进行匹配。
    对于Spark来说,Scala的模式匹配功能也是极其重要的,在spark源码中大量地使用了模式匹配功能。因此为了更好地编写Scala程序,并且更加通畅地看懂Spark的源码,学好模式匹配都是非常重要的。

        val x:Int = 2
        val y:String = x match {
          case 1 =>"one"
          case 2 =>"two"
          case 3 => "three"
          case _ => "other"
        }
        println(y)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    说明
    如果所有case都不匹配,那么会执行case _分支,类似于Java中default语句,
    若此时没有case _分支,那么会抛出MatchError。
    每个case中,不需要使用break语句,自动中断case。
    match case语句可以匹配任何类型,而不只是字面量。
    =>后面的代码块,直到下一个case语句之前的代码是作为一个整体执行,可以使用{}括起来,也可以不括。

    模式守卫

    如果想要表达匹配摸个范围的数据,需要再模式匹配中增加条件守卫。

    def abs(num:Int):Int={
      num match {
      	//如果i>=0,返回i
        case i if i >=0 => i
        //如果i<0,返回-i
        case i if i >0 => -i
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    模式匹配类型

    常量匹配

    def describeConst(x: Any): String = x match {
      case 1 => "Int 1"
      case "hello" => "String hello"
      case true => "Boolean true"
      case '+' => "Char +"
      case _ => ""
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    类型匹配

    println(describeConst(0.1))
    println(describeConst("hello")) //String hello
    println(describeConst(true)) //Boolean true
    
    • 1
    • 2
    • 3

    类型匹配

    (describeType(List("hi", "hello"))) //List List(hi, hello)在底层操作时,会进行泛型擦除,List[String]会被自动判定成List。
    Array不存在泛型擦除,在scala中做隐式转换之后才能调其他的方法。

    def describeType(x: Any): String = x match {
      case i: Int => "Int " + i
      case s: String => "String " + s
      case list: List[String] => "List " + list
      case array: Array[Int] => "Array[Int] " + array.mkString(",")
      case a => "Something else " + a //这里不使用通配符是为了获取到传入的值
    }
    println(describeType(7)) //Int 7
    println(describeType("hello")) //String hello
    println(describeType(List("hi", "hello"))) //List List(hi, hello)
    println(describeType(List(2, 3))) //List List(2, 3)
    println(describeType(Array("hi", "hello")))//Array[Int]
    println(describeType(Array(2,23)))//Array[Int]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    数组匹配

    scala的匹配强大在可以进行模糊匹配。判断顺序为从上到下依次匹配,有一行匹配成功,下面的匹配代码不再执行

        //3. 匹配数组
        for (arr <- List(
          Array(0),
          Array(1, 0),
          Array(0, 1, 0),
          Array(1, 1, 0),
          Array(2, 3, 7, 29),
          Array("hello", 20, 30),
        )) {
          val result = arr match {
            case Array(0) => "0"
            case Array(1, 0) => "Array(1, 0)"
            case Array(x, y) => "Array: " + x + ", " + y //匹配两元素数组
            case Array(0, _*) => "以0开头的数组"
            case Array(x, 1, z) => "第二个元素为1的三元素数组"
            case _ => "something else"
          }
          println(result)
          //0
          //Array(1, 0)
          //以0开头的数组
          //第二个元素为1的三元素数组
          //something else
          //something else
        }
    
    • 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

    列表匹配

    for (list <- List(
      List(0),
      List(1, 0),
      List(1, 1, 0),
      List(0, 3, 5),
      List("hello")
    )){
      val result = list match {
        case List(0) => "0"
        case List(x, y) => "List(x, y): " + x + ", " + y
        case List(1, _*) => "List(1, ……)"
        case List(a) => "List(a): " + a
        case _ => "something else"
      }
      println(result)
      //0
      //List(x, y): 1, 0
      //List(1, ……)
      //something else
      //List(a): hello
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    双冒号匹配

    val list = List(1, 2, 5, 7, 8)
    list match{
      case first :: second :: rest => println(s"first: $first, second $second, rest $rest")
      case _ => println("else")
    }
    //first: 1, second 2, rest List(5, 7, 8)  需要至少三个元素才能匹配上
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    元组匹配

    for (tuple <- List(
      (0, 1),
      (0, 0),
      (0, 1, 0),
      (0, 1, 1),
      (1, 22, 44)
    )){
      val result = tuple match{
        case (a, b) => a + ", " + b
        case (0, _) => "(0, _)"
        case (a, 1, _) => "(a, 1, _) " + a
        case (x, y, z) => "(x, y, z): " + x + ", " + y + ", " +z
        case _ => "else"
      }
      println(result)
      //0, 1
      //0, 0
      //(a, 1, _) 0
      //(a, 1, _) 0
      //(x, y, z): 1, 22, 44
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    元组在变量声明时匹配

    val (x, y) = (10, "hello")
    println(s"x: $x, y: $y")  //x: 10, y: hello
    
    val List(first, second, _*) = List(23, 1, 3, 56)
    println(s"first: $first, second: $second")
    //first: 23, second: 1
    
    val fir :: sec :: rest = List(1, 2, 3, 4, 6)
    println(s"first: $fir, second: $sec, rest: $rest")
    //first: 1, second: 2, rest: List(3, 4, 6)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    for推导式中进行模式匹配

    val list1: List[(String, Int)] = List(("a", 12), ("b", 13), ("c", 34), ("a", 34))
    
    //将list的元素直接定义为元组,对变量赋值
    for ((word, count) <- list1) println(word + ", " + count)
    
    //不考虑某个位置的变量,只遍历key或者value
    for ((word, _) <- list1) println(word)
    
    //指定某个位置的值
    for (("a", count) <- list1) println(count)  //12  34
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    对象匹配

    对象匹配针对对象实例的内容进行匹配。
    在模式匹配中直接新建对象实例并不符合模式匹配的语法规则,因此用伴生对象的apply方法去获取属性和方法。

    object test_MatchObject {
      def main(args: Array[String]): Unit = {
        val student = new Student("alice", 8)
    
       
        val result = student match{
          case Student("alice", 8) => "alice, 8"
          case _ => "else"
        }
        println(result) //alice, 8  匹配成功
      }
    }
    //定义类
    class Student(val name: String, val age: Int)
    
    object Student {
      def apply(name: String, age: Int) = new Student(name, age)
      def unapply(student: Student): Option[(String, Int)] = {
        if (student == null){
          None
        } else{
          Some((student.name, student.age))
        }
      }
    }
    
    • 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
  • 相关阅读:
    2023 MacBook Pro (Apple M2 Pro、macOS Ventura)配置Android开发环境
    [QCM6125][Android13] 大屏显示时任务栏以及虚拟按键靠右问题
    Android基础-进程间通信
    深度学习——第8章 深层神经网络(DNN)
    CA登录服务器
    网安学习-应急响应3
    mongodb如何多表查询,如同时查询店铺以及里面对应的商品
    04-分布式事务解决方案之最大努力通知实战
    async/await与promise
    计算机视觉-数学基础*变换域表示
  • 原文地址:https://blog.csdn.net/weixin_47726676/article/details/126392373