scala-3(模式匹配)


scala使用match关键字声明,每个分支同样使用case关键字,执行逻辑类似于java的switch,但功能更强大

数值匹配

每个分支注明具体数值,当匹配对象的数值与具体数值相等时,进入对应分支

object ModeMatch {
  def main(args: Array[String]): Unit = {
    val oper = '+'
    val n1 = 20
    val n2 = 10
    var res = 0
    oper match {
      case '+' => res = n1 + n2
      case '-' => res = n1 - n2
      case '*' => res = n1 * n2
      case '/' => res = n1 / n2
      // _代表未匹配情况,类似于java中的default分支
      case _ => println("operator erro")
    }
    println("res=" + res)
  }
}

注意事项:

  • 从上到下匹配,匹配到一个就执行对应的代码块
  • 不可以写break,会自动退出match
  • case_相当于javaswitch中的default
  • 如果什么都没有匹配上,并且没有写case_,就会抛出MatchError异常
  • 可以使用多种类型

case分支可以设置条件守卫,在case分支后面增加if条件

object ModeMatch {
  def main(args: Array[String]): Unit = {
    val oper = '+'
    val n1 = 20
    val n2 = 10
    var res = 0
    oper match {
      case '+' => res = n1 + n2
      case '-' => res = n1 - n2
      case '*' => res = n1 * n2
      case _ if oper.equals("3") => res = n1 / n2 => res = n1 / n2
      case _ => println("operator erro")
    }
    println("res=" + res)
  }
}

类型匹配

def matchType(x: Any): Unit = x match {
  case n: Long => println("Long " + n)
  case n: Int => println("Int " + n)
  case 1 => println(1)
  case n: String => println("String " + n)
  case _ => println("match failed")
}

测试:

def main(args: Array[String]): Unit = {
  matchType(1)
  matchType(1L)
  matchType("1")
  matchType('1')
}

输出结果:

Int 1
Long 1
String 1
match failed

注意事项

  • 在匹配时不会自动向上转向,案例中可以看到传入一个Int类型数值,不会被前面的Long类型匹配
  • Map[String,Int]和Map[Int,String]被认为是不同的类型
  • 在进行类型匹配时,编译器会预先检测是否有可能的匹配,如果没有就报错

集合匹配

def matchArr(arr: Array[String]): Unit = arr match {
  // 匹配具有两个元素的数组,且第二个元素必须是"12"
  case Array(_, "12") => print("success!!")
  // 匹配具有一个元素的数组,且元素值必须是"class"
  case Array("class") => println("hello kb11")
  // 匹配具有两个任意元素(字符串类型)的数组
  case Array(str1, str2) => println("hello " + str1 + " " + str2)
  // 匹配具有任意数量各元素(至少一个,且第一个元素值为"class")的数组
  case Array("class", _*) => println("hello kb12 *")
  // 匹配第三个元素值为"123"且元素个数为3的数组,并且把第二个元素的值赋值给b
  case Array(_, b: String, "123") => println(arr(0) + b + "123123")
  case _ => println("object mismatch")
}
  • 当匹配目标为Array(0)时,就必须使用只包含一个0元素的数组匹配
  • 当匹配目标为Array(x,y)时,需要使用包含两个元素的数组匹配,因为设置了变量名,会将数组的变量一一赋值给变量,如果某各位置上的变量名为_,则表示此处有数值,但不使用变量接收
  • 当匹配目标为Array(0,_*)时,需要使用以0元素开头的数组匹配,*表示有0或者多个元素,该标记类似于函数形参中的可变参数,只能出现一次且只能出现在最后

类似的有列表匹配:

object ModeMatch {
  def main(args: Array[String]): Unit = {
    for (list <- Array(List(0), List(1, 0), List(0, 0, 0), List(1, 0, 0))) {
      val result = list match {
        case 0 :: Nil => "0"
        case x :: y :: Nil => x + " " + y
        case 0 :: tail => "0..."
        case _ => "something else"
      }
      println(result)
    }
  }
}
//输出结果
/*
0
1+0
0...
something else
 */

元组匹配

object ModeMatch {
  def main(args: Array[String]): Unit = {
    for (list <- Array((0,1), (1, 0), (1, 1), (1, 0, 2))) {
      val result = list match {
        case (0,_) => "0"//匹配两个元素的,第一个是0
        case (x,0) => x//匹配两个元素的,第二个是0
        case _ => "something else"
      }
      println(result)
    }
  }
}
//输出结果
/*
0
1
something else
something else
 */

对象匹配

case class Teacher(name: String, age: Int)
def match3(teacher: Teacher): Unit = teacher match {
  // 匹配name属性为zs,age属性37的teacher
  case Teacher("zs", 37) => println("case1 matched")
  // 匹配age属性20的teacher,name属性任意
  case Teacher(_, 20) => println("case2 matched")
  // 匹配name属性为bob的teacher
  case _ if teacher.name == "bob" => println("special case matched")
  case x: Teacher => println("type mismatch")
}

匹配对象过程实际会调用对象的unapply方法,如果返回Some则会匹配成功,如果返回None匹配失败

测试案例:

object Test0426 {
  def main(args: Array[String]): Unit = {
    val p: Person = new Person("zs", 18)
    p match {
      case Person("zs", age) => println("case1 matched age " + age)
      case _ => println("type mismatch")
    }
  }
}

object Person {
  val name: String = "zs"
  val age: Int = 18

  def apply: Person = new Person()

  def apply(name: String, age: Int): Person = new Person(name, age)
  
  def unapply(arg: Person): Option[(String, Int)] = Some((Person.name, Person.age + 20))
}

class Person(name: String, age: Int) {
  def this() {
    this("ls", 20)
  }
}

// 输出结果:case1 matched age 38

可以看到实际输入age属性为18,输出age属性为38

将unapply方法返回值改为None后,输出结果:type mismatch,虽然实际name属性为'zs',符合匹配条件,但是最终结果匹配失败

模式匹配运用

val map = Map("a" -> 1, "b" -> 2, "c" -> 0)
// 普通遍历,会输出所有键值对
for ((k, v) <- map){
  println(s"k:$k v:$v")
}

// 只会匹配V值为0的键值对
for ((k, 0) <- map){
  println(s"k:$k v:0")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值