Scala---模式匹配

Scala之模式匹配

Scala 中的模式匹配类似于 Java 中的 switch 语法



基本语法

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

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

在这里插入图片描述
说明

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

模式守卫

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

    println("===模式守卫============")
    def abs(num:Int):Int ={
      num match {
        case i if i >= 0 => i
        case i if i < 0 => -i
      }
    }

    println(abs(90))
    println(abs(-34))

在这里插入图片描述

匹配常量

Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等

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

    println(describeConst("hello"))//String two
    println(describeConst(1))//Int one
    println(describeConst(true))//Boolean true
    println(describeConst(false))//???

匹配类型

需要进行类型判断时,可以使用前文所学的 isInstanceOf[T]和 asInstanceOf[T],也可使 用模式匹配实现同样的功能。

println("==============匹配类型==============")
    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(36))
    println(describeType("hello"))
    println(describeType(List("hi","hello")))
    println(describeType(List(11,22)))
    println(describeType(Array("hi","hello")))
    println(describeType(Array(11,22)))

在这里插入图片描述

匹配数组

scala 模式匹配可以对集合进行精确的匹配,例如匹配只有两个元素的、且第一个元素为 0 的数组

 println("============匹配数组=============")
    for (arr <-List(
      Array(0),
      Array(1,0),
      Array(0,1,0),
      Array(4,8,9,23),
      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)
    }

在这里插入图片描述

匹配列表

println("=======匹配列表=======")
    for (list <- List(
      List(0),
      List(1,0),
      List(0,0,0),
      List(1,1,0),
      List(88),
      List("hello")
    )){
      val result = list match {
        case List(0) =>"0"
        case List(x,y) =>"List(x,y):"+ x +","+y
        case List(0,_*) =>"List(0,....)"
        case List(a) => "List(a):" +a
        case _ =>"something else"
      }
      println(result)
    }

在这里插入图片描述

println("=============匹配列表(方式二)===========")
    //方式二
    val list = List(1,3,5,7,8,9)
    list match {
      case first :: second :: rest=>println(s"first:$first ,scond:$second ,rest:$rest")
      case _=> println("something else")
    }

在这里插入图片描述

匹配元组

    println("===========匹配元组===============")
    for (tuple <- List(
      (0,1),
      (0,0),
      (0,1,0),
      (0,1,1),
      (1,23,65),
      ("hello","scala",111)
    )){
      val result = tuple match {
        case (a,b) =>"" + a + "," + b
        case (0 ,_) =>"(0,_)"
        case (a ,1,_) =>"(a,1,_)" +a
        case _ =>"something else"
      }
      println(result)
    }

在这里插入图片描述

匹配对象及样例类

匹配对象

基本语法

 def main(args: Array[String]): Unit = {
    val student = new Student("zhangsan",19)
    //针对对象的实例内容进行匹配
    val result = student match {
      case  Student("zhangsan",19)=>"zhangsan,19"
      case _=>"else"
    }
    println(result)
  }
}
//定义类
class Student(val name:String,val age:Int)

//定义伴生对象
object Student{
  def apply(name:String,age:Int):Student = new Student(name,age)
  //必须实现一个unapply方法,用来对对象属性进行拆解
  def unapply(student: Student):Option[(String,Int)]={
    if (student ==null){
      None
    }else{
      Some((student.name,student.age))
    }
  }

在这里插入图片描述
注意

1.val student = Student("zhangsan",19),该语句在执行时,实际调用的是 Student 伴生对象中的apply 方法,因此不用 new 关键字就能构造出相应的对象。
2.当将 Student("zhangsan",19)写在 case 后时[case Student("zhangsan",19)=>"zhangsan,19"],会默认调用 unapply 方法(对象提取器),student作为 unapply 方法的参数,unapply 方法将student对象的 name 和 age 属性提取出来,与Student("zhangsan",19)中的属性值进行匹配
3.case 中对象的 unapply 方法(提取器)返回 Some,且所有属性均一致,才算匹配成功,属性不一致,或返回 None,则匹配失败。
4.若只提取对象的一个属性,则提取器为 unapply(obj:Obj):Option[T]
5.若提取对象的多个属性,则提取器为 unapply(obj:Obj):Option[(T1,T2,T3…)]
6.若提取对象的可变个属性,则提取器为 unapplySeq(obj:Obj):Option[Seq[T]]

样例类

基本语法

  def main(args: Array[String]): Unit = {
    val student = new Student1("zhangsan",20)
    //针对对象实例的内容进行匹配
    val result = student match {
      case Student1("zhangsan",20) => "zhangsan,20"
      case _=>"Else"
    }
    println(result)
  }
}
//定义成样例类
case class Student1(name:String,age:Int)

在这里插入图片描述

注意

1.样例类仍然是类,和普通类相比,只是其自动生成了伴生对象,并且伴生对象中自动提供了一些常用的方法,如 apply、unapply、toString、equals、hashCode 和 copy。
2. 样例类是为模式匹配而优化的类,因为其默认提供了 unapply 方法,因此,样例类可以直接使用模式匹配,而无需自己实现 unapply 方法。
3. 构造器中的每一个参数都成为 val,除非它被显式地声明为 var(不建议这样做)

偏函数中的模式匹配

偏函数也是函数的一种,通过偏函数我们可以方便的对输入参数做更精确的检查

例如
该偏函数的输入类型为 List[Int],而我们需要的是第一个元素是 0 的集合,这就是通过模式匹配实现的

偏函数定义

val second: PartialFunction[List[Int], Option[Int]] = {
 case x :: y :: _ => Some(y)
}

在这里插入图片描述注:该偏函数的功能是返回输入的 List 集合的第二个元素

案例

实现元素第一个不变,第二个元素*2

  def main(args: Array[String]): Unit = {
    val list:List[(String,Int)]=List(("a",12),("b",20),("c",30),("a",13))
    //1.map转换,实现key不变,value*2
    val newList = list.map(tuple =>(tuple._1,tuple._2*2))
    //2.模式匹配对元组元素赋值,实现功能
    val newList2 =list.map(
      tuple =>{
        tuple match {
          case (word,count) =>(word,count*2)
        }
      }
    )
    //3.省略lambda表达式写法
    val newList3 =list.map {
          case (word,count) =>(word,count*2)
    }
    println(newList)
    println(newList2)
    println(newList3)
  }
/*案例二*/
    //偏函数的应用,求绝对值
    //对输入数据分不同的情形:正 负 0
    val positiveAbs:PartialFunction[Int,Int]={
      case x if x>0 => x
    }
    val negativeAbs:PartialFunction[Int,Int]={
      case x if x<0 => -x
    }
    val zeroAbs:PartialFunction[Int,Int]={
      case 0 => 0
    }
    def abs(x:Int):Int=(positiveAbs orElse negativeAbs orElse zeroAbs) (x)

    println(abs(-20))
    println(abs(0))
    println(abs(30))
  }

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值