【Scala】模式匹配

Scala 中的模式匹配 类似于 Java 中的 switch 语法
模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需
要匹配时,会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹
配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _ 分支,
类似于 Java default 语句。 
var a: Int = 10
 var b: Int = 20
 var operator: Char = 'd'
 var result = operator match {
 case '+' => a + b
 case '-' => a - b
 case '*' => a * b
 case '/' => a / b
 case _ => "illegal"
}
 println(result)
1 )如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java default 语句,
若此时没有 case _ 分支,那么会抛出 MatchError
2 )每个 case 中,不需要使用 break 语句,自动中断 case
3 match case 语句可以匹配任何类型,而不只是字面量。
4 => 后面的代码块,直到下一个 case 语句之前的代码是 作为一个整体执行 ,可以
使用 {} 括起来,也可以不括。

模式守卫

如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。
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(-5))

匹配常量

def describe(x: Any) = x match {
 case 5 => "Int five"
 case "hello" => "String hello"
 case true => "Boolean true"
 case '+' => "Char +"

匹配类型

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

object Test {

  def describe(x: Any) = x match {
    case i: Int => "Int"
    case s: String => "String hello"
    case m: List[_] => "List"
    case c: Array[Int] => "Array[Int]"
    case someThing => "something else " + someThing
  }

  def main(args: Array[String]): Unit = {

    //泛型擦除
    println(describe(List(1, 2, 3, 4, 5)))
    //数组例外,可保留泛型
    println(describe(Array(1, 2, 3, 4, 5, 6)))
    println(describe(Array("abc")))

  }
}

//List
//Array[Int]
//something else [Ljava.lang.String;@6debcae2

匹配数组

for (arr <- Array(Array(0), Array(1, 0), Array(0, 1, 0), 
Array(1, 1, 0), Array(1, 1, 0, 1), Array("hello", 90))) { // 对
一个数组集合进行遍历
 val result = arr match {
 case Array(0) => "0"             //匹配 Array(0) 这个数组
 case Array(x, y) => x + "," + y //匹配有两个元素的数组(将第一个数赋给x,第二个赋给y)
 case Array(0, _*) => "以 0 开头的数组"     //匹配以 0 开头和数组
 case Array(x,1,y) => "中间为1的三元数组"
 case _ => "something else"
 }
 println("result = " + result)
 }

//_ 为任意一个元素 _*为任意个任意元素

匹配列表

方式1:

//list 是一个存放 List 集合的数组
 for (list <- Array(List(0), List(1, 0), List(0, 0, 0), List(1, 
0, 0), List(88))) {
 val result = list match {
 case List(0) => "0" //匹配 List(0)
 case List(x, y) => x + "," + y //匹配有两个元素的 List
 case List(0, _*) => "0 ..."
 case _ => "something else"
 }
 println(result)

方式2:

list match {
 case first :: second :: rest => println(first + "-" + second + "-" + rest)
 case _ => println("something else")

//第一个元素::第二个元素::其他元素(可以是空列表 Nil)
//当元素为1个时 case _

匹配元组

for (tuple <- Array((0, 1), (1, 0), (1, 1), (1, 0, 2))) {
 val result = tuple match {
 case (0, _) => "0 ..." //是第一个元素是 0 的元组
 case (y, 0) => "" + y + "0" // 匹配后一个元素是 0 的对偶元组
 case (a, b) => "" + a + " " + b
 case _ => "something else" //默认
 }
 println(result)

扩展用法

val (x,y) = (10,"www")
val List(first,second,_*) = List(21,21,34,35)
val fir :: sce :: rest = List(21,34,23,43)

for推导式模式匹配

val list:List[(String,Int)] = List(("a",12),("b",34))

for(elem <- list){
    elem._1 elem._2
}

for( (x,y) <- list ){
    x y
}

//只遍历key或value
for( (word, _) <- list){
    println(word)
}

//筛选
for(("a",count) <- list){
   count
}

匹配对象及样例类

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 TestMatchUnapply {
 def main(args: Array[String]): Unit = {
 val user: User = User("zhangsan", 11)
 val result = user match {
 case User("zhangsan", 11) => "yes"
 case _ => "no"
 }
 println(result)
 }
}
val user = User("zhangsan",11) ,该语句在执行时,实际调用的是 User 伴生对象中的
apply 方法,因此不用 new 关键字 就能构造出相应的对象。
当将 User("zhangsan", 11) 写在 case 后时 [case User("zhangsan", 11) => "yes"] ,会默
认调用 unapply 方法 ( 对象提取器 ) user 作为 unapply 方法的参数 unapply 方法
user 对象的 name age 属性提取出来,与 User("zhangsan", 11) 中的属性值进行
匹配
case 中对象的 unapply 方法 ( 提取器 ) 返回 Some ,且所有属性均一致,才算匹配成功 ,
属性不一致,或返回 None ,则匹配失败。
若只提取对象的一个属性,则提取器为 unapply (obj:Obj): Option[ T ]
若提取对象的多个属性,则提取器为 unapply (obj:Obj): Option[ (T1,T2,T3…) ]
若提取对象的可变个属性,则提取器为 unapplySeq (obj:Obj): Option[ Seq[T] ]

样例类

case class User(name: String, age: Int)
object TestMatchUnapply {
 def main(args: Array[String]): Unit = {
     val user: User = User("zhangsan", 11)
     val result = user match {
         case User("zhangsan", 11) => "yes"
         case _ => "no"
     }
     println(result)
 }
}
1 )语法:
case class Person (name: String, age: Int)
2 )说明
○1 样例类仍然是类,和普通类相比,只是其自动生成了伴生对象,并且伴生对象中
自动提供了一些常用的方法,如 apply unapply toString equals hashCode copy
○2 样例类是为模式匹配而优化的类,因为其默认提供了 unapply 方法,因此,样例
类可以直接使用模式匹配,而无需自己实现 unapply 方法。
○3 构造器中的每一个参数都成为 val ,除非它被显式地声明为 var (不建议这样做)
case class User(name: String, age: Int)
object TestMatchUnapply {
 def main(args: Array[String]): Unit = {
     val user: User = User("zhangsan", 11)
     val result = user match {
         case User("zhangsan", 11) => "yes"
         case _ => "no"
     }
     println(result)
 }
}

for 表达式中的模式匹配

object TestMatchFor {
 def main(args: Array[String]): Unit = {
 val map = Map("A" -> 1, "B" -> 0, "C" -> 3)
 for ((k, v) <- map) { //直接将 map 中的 k-v 遍历出来
 println(k + " -> " + v) //3 个
 }
 println("----------------------")
 //遍历 value=0 的 k-v ,如果 v 不是 0,过滤
 for ((k, 0) <- map) {
 println(k + " --> " + 0) // B->0
 }
 println("----------------------")
 //if v == 0 是一个过滤的条件
 for ((k, v) <- map if v >= 1) {
 println(k + " ---> " + v) // A->1 和 c->33
 }
 }
}

偏函数 

将问题分解多种情况的子问题,分别实现。

val second: PartialFunction[List[Int], Option[Int]] = {
 case x :: y :: _ => Some(y)
}
代码会被 scala 编译器翻译成以下代码,与普通函数相比,只是多了一个用于参数 检查的函数——isDefinedAt ,其返回值类型为 Boolean
val second = new PartialFunction[List[Int], Option[Int]] {
 //检查输入参数是否合格
 override def isDefinedAt(list: List[Int]): Boolean = list match 
{
 case x :: y :: _ => true
 case _ => false
 }
 //执行函数逻辑
 override def apply(list: List[Int]): Option[Int] = list match 
{
 case x :: y :: _ => Some(y)
 }
}
偏函数不能像 second(List(1,2,3)) 这样直接使用,因为这样会直接调用 apply 方法,而应
该调用 applyOrElse 方法,如下
second.applyOrElse(List(1,2,3), (_: List[Int]) => None)
applyOrElse 方法的逻辑为 if ( ifDefinedAt( list ) ) apply( list ) else default 。如果输入参数满
足条件,即 isDefinedAt 返回 true ,则执行 apply 方法,否则执行 defalut 方法, default 方法
为参数不满足要求的处理逻辑。

来源:

尚硅谷 

Scala学习笔记(六) Scala的偏函数和偏应用函数 - 简书 (jianshu.com)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

返返返

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值