Scala之模式匹配(十一)

基本概念

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

守卫
基本概念

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

案例实操
val ch = 10
ch match {
  case '+' => sign = 1
  case '-' => sign = -1
  case _ if ch.toString.equals("10") => digit = 10
  case _ => sign = 2
}

注意:模式总是从上往下进行匹配;如果带守卫的这个模式不能匹配,则捕获所有的模式(case _)会被用来尝试进行匹配。

模式中的变量
基本概念

如果在case关键字后跟变量名,那么匹配的表达式会被赋值给那个变量。

案例实操
val ch = 'U'
ch match {
  case '+' => println("ok")
  case mychar => println("ok~" + mychar)
  case _ => println("ok~")
}

// 输出:ok~U
类型匹配
基本概念

在Scala中进行类型匹配时,更倾向于使用这样的模式匹配方式,而不是使用isInstanceOf 操作符。

案例操作
// 类型匹配, obj 可能有如下的类型
val a = 4
val obj = if(a == 1) 1
else if(a == 2) "2"
else if(a == 3) BigInt(3)
else if(a == 4) Map("aa" -> 1)
else if(a == 5) Map(1 -> "aa")
else if(a == 6) Array(1, 2, 3)
else if(a == 7) Array("aa", 1)
else if(a == 8) Array("aa")

// 根据obj的类型进行匹配
val result = obj match {
case a : Int => a
case b : Map[String, Int] => "对象是一个字符串-数字的Map集合"
case c : Map[Int, String] => "对象是一个数字-字符串的Map集合"
case d : Array[String] => "对象是一个字符串数组"
case e : Array[Int] => "对象是一个数字数组"
case f : BigInt => Int.MaxValue
case g : Array[Any] => "任意类型的数组"
case _ => "啥也不是"
}
println(result)	// 输出:对象是一个字符串-数字的Map集合

注意事项:

  1. 在进行类型匹配时,编译器会预先检测是否可能的匹配,如果没有的话就会报错
  2. Map[String,Int] 和 Map[Int,String]是两种不同的类型
  3. 如果 case _ 出现在match中间,表示隐藏变量名,就是不使用,而不是表示默认匹配
匹配数组,列表和元组
匹配数组
arr match {
  case Array(0) => "0"
  case Array(x, y) => ArrayBuffer(y,x)      // 转变为可变数组
  case Array(0, _*) => "以0开头和数组"
  case _ => "什么集合都不是"
}

详解:第一个模式匹配包含0的数组;第二个模式匹配任何带有两个元素的数组,并将两个元素存入到可变数组ArrayBuffer中,第三个表达式匹配任何以零开始的数组。

匹配列表
list match {
  case 0 :: Nil => "0" // Nil 表示后面没有值
  case x :: y :: Nil => x + " " + y //
  case 0 :: tail => "0 ..." //  tail表示后面0到多个参数
  case _ => "something else"
}

详解:第一个模式匹配表示列表只有一个元素并且为0;第二个表达式匹配任何带有两个元素的列表;第三个表达式匹配任何以0开始的列表。

匹配元组
pair match { //
  case (0, _) => "0 ..." // _ 表示忽略这个数据
  case (y, 0) => y //
  case (x, y) => (y, x)
  case _ => "other" 
}

详解:第一个表达式匹配以0开头的元组,第二个表达式匹配第一个元素为任意值第二个元素为0,第三个表达式匹配任意两个元素的元组。

for表达式中的模式
基础概念

我们可以在for推导式中使用带变量的模式;对每一个遍历到的值,这些变量都会被绑定;使得我们可以方便地遍历映射。

案例操作
val map = Map("A"->1, "B"->0, "C"->3)

//说明: 只遍历出 value = 0 的key-value,其他的会被过滤掉
for ((k, 0) <- map) {
  println(k + " --> " + 0)
}
//说明: 相当于守卫的功能,是上面代码的另一种写法
for ((k, v) <- map if v == 0) {
  println(k + " ---> " + v)
}
样例类
基础概念

样例类是一种特殊的类,他们经过优化以被用于模式匹配。还有就是样例类都是经过序列化操作的。

案例操作
abstract class Amount
case class Dollar(value: Double) extends Amount
case class Currency(value: Double, unit: String) extends Amount

样例类注意事项:

  1. 构造器中的每一个参数都称为val——除非它被显式地声明为var
  2. 在伴生对象中提供apply方法让你不用new关键字就能构造出相应的对象
  3. 将会自动生成 toString,equals,hashCode和copy方法
  4. 样例类是为模式匹配而优化的类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值