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)

说明
如果所有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
  }

模式匹配类型

常量匹配

def describeConst(x: Any): String = x match {
  case 1 => "Int 1"
  case "hello" => "String hello"
  case true => "Boolean true"
  case '+' => "Char +"
  case _ => ""
}

类型匹配

println(describeConst(0.1))
println(describeConst("hello")) //String hello
println(describeConst(true)) //Boolean true

类型匹配

(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]

数组匹配

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
    }

列表匹配

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
}

双冒号匹配

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)  需要至少三个元素才能匹配上

元组匹配

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
}

元组在变量声明时匹配

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)

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

对象匹配

对象匹配针对对象实例的内容进行匹配。
在模式匹配中直接新建对象实例并不符合模式匹配的语法规则,因此用伴生对象的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))
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值