scala学习笔记之模式匹配

Scala学习笔记

模式匹配

  • 模式匹配类似于java中的switch语法,但是要更加强大。

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

  • 基本语法:

    /**
    a match {
    case '1' => print(1)
    case '2' => print(2)
    case _ => print('其他')
    }
    **/
    
    1. 如果所有的case都不匹配,那么会匹配case_分支,若没有该分支,则抛出MatchError
    2. 每个case中,都不用break语句,自动中断case
    3. match case语句可以匹配任何类型,不只是字面量
    4. => 后面的代码块会作为一个整体执行,可以用花括号{},也可以不用

模式守卫

  • 如果想要匹配某个范围内的数据,就需要用到模式守卫,即在模式匹配中添加条件守卫

      def main(args: Array[String]): Unit = {
        def abs(x:Int) = x match {
          case i: Int if i >= 0 => i
          case j: Int if j < 0 => -j
          case _ => "Type illegal"
        }
        println(abs(34),abs(-12),abs(12))
      }
    /**
    输出结果为:
    (34,12,12)
    **/
    

模式匹配类型

  • 匹配常量

    • scala中,模式匹配中可以匹配所有的字面量,包括字符串、字符、数字、布尔值等等。
        println(test(6))
        println(test("6"))
        println(test(6>5))
        println(test('6'))
    
        def test(x:Any) = x match {
          case 6 => "Int 6"
          case "6" => "String 6"
          case true => "Boolean true"
          case '6' => "Char 6"
          case _ => "_"
        }
    /**
    输出结果为:
    Int 6
    String 6
    Boolean true
    Char 6
    **/
    
  • 匹配类型

    • 在scala的模式匹配中,需要进行类型判断的时候,可以通过isInstanceOf[]或asInstanceOf[],也可以使用模式匹配实现相同的功能
    • 注意,在模式匹配中会出现对集合的范式擦除的问题,只有数组例外,可以保留范式。
      def main(args: Array[String]): Unit = {
        println(caseType(List(1,2,3)))
        println(caseType(List("123")))
        println(caseType(Array(1,2,3)))
        println(caseType(Array("123")))
        def caseType(x:Any)=x match {
          case ls:List[String] => "String list"
          case li:List[Int] => "Int list"
          case arrays:Array[String] => "String array"
          case ai:Array[Int] => "Int array"
          case _ => "_"
        }
      }
    /**
    可以在下面的结果中看到结果中list的泛型被擦除了,
    不论泛型为那种都被在前的 case ls:List[String] => "String list"这行吸收了
    而数组array则没有这种问题
    输出结果为:
    String list
    String list
    Int array
    String array
    **/
    
  • 匹配数组

    • scala模式匹配可以对集合进行精确的匹配,如只有两个元素的数组、第一个元素为0的数组等
      def main(args: Array[String]): Unit = {
        for (a <- Array(Array(1),Array(0),Array(1,3),Array(1,2,3,4),Array(0,1,2))){
          val result = a match {
            case Array(0) => "0"
            case Array(x,y) => x+","+y
            case Array(0,_*) => "start with 0"
            case _ => "_"
          }
          println(result)
        }
      }
    /**
    输出结果为:
    _
    0
    1,3
    _
    start with 0
    **/
    
  • 匹配对象

    • 在伴生对象中实现unapply方法,提供提取器,case案例在匹配时会调用提取器提取对象中的属性进行匹配。
    • case中对象的unapply方法返回Some,且所有属性均一致时才算匹配成功,属性不一致,返回None,匹配失败。
    • 根据匹配需求不同,有时候需要匹配的属性也不同,这些时候所用的提取器也不尽相同:
      • 若只提取一个属性,则用: unapply(obj:Obj):Option[T]
      • 若提取多个属性,则用:unapply(obj:Obj):Option[(T1,T2,T3,T4,…)]
      • 若提取可变个属性,则用:unapply(obj:Obj):Option[Seq[T]]
    class User(val name:String,val age:Int)
    
    object User{
      def apply(name: String, age: Int): User = new User(name, age)
    
      def unapply(user: User): Option[(String, Int)] = {
        if (user == null){
          None
        }else {
          Some(user.name, user.age)
        }
      }
    }
    object TestCaseObject {
      def main(args: Array[String]): Unit = {
        val user:User = User("Zhan",12)
        val result = user match {
          case User("Zhan",12) => "match"
          case _ => "_"
        }
        println(result)
      }
    }
    /**
    输出结果为:
    match
    **/
    
  • 样例类:

    • 通过case修时的类为样例类。
      • 样例类依然是类,只是其自动生成了伴生对象,且自动实现了一些常用的方法,如apply、unapply、toString、equals、hashCode和copy等
      • 样例类是为模式匹配而优化的类,其默认提供unapply方法,因此可以直接用于模式匹配
      • 构造器的每个参数都默认为val,除非它被显式的声明为var
    case class User(name:String,age:Int)
    
    object TestCaseClass {
      def main(args: Array[String]): Unit = {
        val user = User("Alice",12)
        val result = user match {
          case User("Alice",12) => "match"
          case _ => "_"
        }
        println(result)
      }
    }
    /**
    输出结果为:
    match
    **/
    

其他情况下的模式匹配

  • 声明变量中的模式匹配

    • 在声明变量时可以通过各种模式匹配套用格式,获取满足条件的值
    object TestCase2 {
      def main(args: Array[String]): Unit = {
        val (x,y) = (2,4)
        println(x,y)
    
        val Array(a,b,c,_*) = Array(1,2,3,4,5,6)
        println(a,b,c)
      }
    }
    /**
    (2,4)
    (1,2,3)
    **/
    
  • for循环中的模式匹配

    object TestCaseFor {
      def main(args: Array[String]): Unit = {
        val map = Map(1->"1",2->"2",3->"3")
        for ((k,v) <- map){
          println(k,v)
        }
      }
    }
    /**
    (1,1)
    (2,2)
    (3,3)
    **/
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值