Scala核心编程(12)- 模式匹配

match介绍

Scala中的模式匹配类似于Java中的switch语法,但是更加强大

式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case _ 分支,类似于Javadefault语句

应用案例 

    val category: String = "vip"
    category match {
      case "vip" => println("会员")
      case "sVip" => println("超级会员")
      case "normal" => println("普通会员")
      case "customer" => println("普通用户")
      case _ => println("游客访问")
      // 下一行和上一行是相同的情况,所以永远都不会执行到
      case _ => println("游客访问....第二行")
    }
## 输出
会员

 注意事项

  • 如果所有case都不匹配,那么执行case _ 分支,类似于Java中default语句
  • 如果所有case都不匹配,又没有写case _ 分支,那么会抛出MatchError
  • 每个case中,不用break语句,自动中断case
  • 可以在match中使用其它类型,而不仅仅是字符,可以是表达式
  • => 类似于 java swtich 的 :
  • => 后面的代码块到下一个case, 是作为一个整体执行,可以使用{} 括起来,也可以不括。
  • case可以出现多个相同的分类,但是第一个出现的情形可能被执行到,之后出现的相同情形都不会被执行到

 守卫案例

果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守

    for (ch <- "+-*/%.") {
      ch match {
        case '+' => println("case+: 加法运算")
        case '-' => println("case-: 减法运算")
        case '*' => println("case*: 乘法运算")
        case '/' => println("case/: 除法运算")
        case '%' => println("case%: 求余运算")
        case _ => println("case_:不支持的运算符")
      }
    }
## 输出
case+: 加法运算
case-: 减法运算
case*: 乘法运算
case/: 除法运算
case%: 求余运算
case_:不支持的运算符

match中的变量 

果在case关键字后跟变量名,那么match前表达式的值会赋给那个变

    for (name <- List("+", "关晓彤", "其他")) {
      name match {
        case "+" => println("case +: 某个固定字符")
        case name => println("case name: 嗨:" + name)
        case _ => println("case _: 默认输出")
      }
    }
## 输出
case +: 某个固定字符
case name: 嗨:关晓彤
case name: 嗨:其他

匹配类型

以匹配对象的任意类型,这样做避免了使用isInstanceOfasInstanceOf

## 注意事项
1.Map[String, Int] 和Map[String, String]是两种不同的类型,严格按照泛型推断。

2.在进行类型匹配时,编译器会预先检测是否有可能的匹配,如果没有则报错.

3.可以将obj赋值给对应的变量

4.如果case _:(类型),则表示要隐藏变量名,因为不需要使用变量名,不是表示默认匹配

 def testType(obj: Any): Unit = {
    val result = obj match {
      case a: String => println("case String: 是一个字符串")
      case b: Int => {
        println("case Int: 是一个数字")
        b
      }
      case _: BigInt => {
        println("case BigInt: 只需要知道类型就行了,不需要使用该变量值")
        Int.MaxValue
      }
      // c和d是两种不同的类型
      case c: Map[String, Int] => {
        println("case map: 是一个字符串-数字的map集合")
        c
      }
      case d: Map[String, String] => {
        println("case map: 是一个字符串-字符串的map集合")
        d
      }
      case e: Array[Int] => println("case array: 是一个数字数组")
      case f: Array[String] => println("case array: 是一个字符串数组")
      case g: Boolean => println("case Boolean: 是一个布尔类型数据")
      case _ => println("case _: 默认值")
    }
    println("输出的结果(其实也就是入参):" + result)
    println()
  }

  def main(args: Array[String]): Unit = {
    testType()
    testType(Map(("AA" -> "aa")))
    testType(Map(("AA" -> 13)))
    testType(13)
    testType(BigInt(12))
  }
## 输出
case _: 默认值
输出的结果(其实也就是入参):()

case map: 是一个字符串-数字的map集合
输出的结果(其实也就是入参):Map(AA -> aa)

case map: 是一个字符串-数字的map集合
输出的结果(其实也就是入参):Map(AA -> 13)

case Int: 是一个数字
输出的结果(其实也就是入参):13

case BigInt: 只需要知道类型就行了,不需要使用该变量值
输出的结果(其实也就是入参):2147483647

匹配数组

  1. Array(0)    匹配只有一个元素且为0的数组
  2. Array(x,y)  匹配数组有两个元素
  3. Array(Int)   匹配数组是数字数组
  4. Array(0,_*)  匹配数组以0始 

PS: 如果多个匹配都满足,会执行第一个满足的情形

    for (arr <- Array(Array(0), Array(1, 0), Array(0, 1), Array(0, 1, 0), Array("abc", 1, 0, 1))) {
      val result = arr match {
        case Array(0) => {
          println("case Array(0): 匹配只有一个元素且为0的数组")
          arr
        }
        case Array(x, y) => {
          println("case Array(x,y): 匹配有两个元素的数组")
          arr
        }
        case Array(0, _*) => {
          println("case Array(0, _*): 匹配以0元素开始的数组")
          arr
        }
        case _: Array[Int] => {
          println("case Array[Int] : 匹配数字数组")
          arr
        }
        case _ => {
          println("case _ : 默认匹配")
          arr
        }
      }
      print("数组打印:")
      result.foreach(x => print(x + ", "))
      println()
      println()
    }
## 输出
case Array(0): 匹配只有一个元素且为0的数组
数组打印:0, 

case Array(x,y): 匹配有两个元素的数组
数组打印:1, 0, 

case Array(x,y): 匹配有两个元素的数组
数组打印:0, 1, 

case Array(0, _*): 匹配以0元素开始的数组
数组打印:0, 1, 0, 

case _ : 默认匹配
数组打印:abc, 1, 0, 1, 

匹配列表

    for (list <- Array(List(0), List(3), List(1, 0), List(0, 0, 1), List(0, 0, 2))) {
      val result = list match {
        case 0 :: Nil => {
          println("case List(0): 匹配元素只有0的列表")
          list
        }
        case x :: Nil => {
          println("case List(x): 匹配元素只有x的列表")
          list
        }
        case x :: y :: Nil => {
          println("case List(x,y): 匹配有两个元素的列表")
          list
        }
        case 0 :: tail => {
          println("case List(0,***): 匹配第一个元素是0的列表")
          list
        }
        case _ => {
          println("case _: 匹配默认值")
          list
        }
      }
      println(result)
## 输出
case List(0): 匹配元素只有0的列表
List(0)
case List(x): 匹配元素只有x的列表
List(3)
case List(x,y): 匹配有两个元素的列表
List(1, 0)
case List(0,***): 匹配第一个元素是0的列表
List(0, 0, 1)
case List(0,***): 匹配第一个元素是0的列表
List(0, 0, 2)

 匹配元组

    for (tuple <- Array(Tuple1(0), (0, 1), (13, 30), (0, 2, 1), (0, 1, 2, 3))) {
      val result = tuple match {
        case (0, _) => {
          println("case Tuple(0,*): 匹配以0作为首位的两位元组")
          tuple
        }
        case Tuple1(x) => {
          println("case Tuple(x): 匹配值有一个元素的元组")
          tuple
        }
        case (_, _, 1) => {
          println("case Tuple(*,*,1): 匹配以1结尾的三位元组")
          tuple
        }
        case (x, y) => {
          println("case Tuple(x,y): 匹配两位元组,将原元组元素互换位置")
          (y, x)
        }
        case _ => {
          println("case _: 匹配默认值")
          tuple
        }
      }
      println(result)
## 输出
case Tuple(x): 匹配值有一个元素的元组
(0)
case Tuple(0,*): 匹配以0作为首位的两位元组
(0,1)
case Tuple(x,y): 匹配两位元组,将原元组元素互换位置
(30,13)
case Tuple(*,*,1): 匹配以1结尾的三位元组
(0,2,1)
case _: 匹配默认值
(0,1,2,3)

匹配对象

匹配规则:

  1. 对象必须实现对象提取器方法对象在case关键字后,会默认的调用该方法
  2. case后面对象参数是一个的时候实现unapply方法,
  3. case后面对象参数是多个的时候实现unapplySeq方法
  4. 如果返回Some集合视为成功
  5. 返回none集合视为失败
  object Start {
    //在case后会默认调用该方法
    def unapply(d: String): Option[String] = {
      if (d.contains(",")) None else Some(d)
    }


    //在创建对象的时候会调用该方法
    def apply(d: String): String = s"hello ,$d !"
  }

  object StartList {
    //在case后会默认调用该方法

    def unapplySeq(s: String): Option[Seq[String]] = {
      if (s.contains(",")) Some(s.split(",")) else None
    }

    //在创建对象的时候会调用该方法
    def apply(d: String): String = s"hello ,$d !"
  }

  def testObj(): Unit = {
    for (name <- Array("关晓彤", "关晓彤,沈腾,贾玲", "关晓彤,沈腾,贾玲,华晨宇")) {
      val result = name match {
        //case中的对象会默认调用对象中的unapply方法,返回Some集合则匹配成功,返回none就是失败
        case Start(n) => {
          println("case Start(n): " + n)
          n
        }
        case StartList(first, middle, last) => {
          println(s"case StartList(first, middle, last): $first,$middle,$last")
          List(first, middle, last)
        }
        case _ => {
          println("case _ : 匹配默认值")
        }
      }
      println(s"result: $result")
    }
  }
  def main(args: Array[String]): Unit = {
    testObj()
  }
## 输出 
case Start(n): 关晓彤
result: 关晓彤
case StartList(first, middle, last): 关晓彤,沈腾,贾玲
result: List(关晓彤, 沈腾, 贾玲)
case _ : 匹配默认值
result: ()

变量声明中的模式

    val (x, y) = (1, 2)
    println("x = " + x)
    println("y = " + y)

    val (q, r) = BigInt(10) /% 3 // 包含了2个连续的运算符
    println("10除3的商:q = " + q)
    println("10除3的余:r = " + r)

    val arr = Array(1, 7, 2, 9)
    val Array(first, second, _*) = arr
    println("first: " + first + " ;  second: " + second)
## 输出
x = 1
y = 2
10除3的商:q = 3
10除3的余:r = 1
first: 1 ;  second: 7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值