前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2021年大数据常用语言Scala(三十三):scala高级用法 模式匹配

2021年大数据常用语言Scala(三十三):scala高级用法 模式匹配

作者头像
Lansonli
发布2021-10-11 15:34:01
7290
发布2021-10-11 15:34:01
举报
文章被收录于专栏:Lansonli技术博客Lansonli技术博客

模式匹配

scala中有一个非常强大的模式匹配机制,可以应用在很多场景:

  • switch语句
  • 类型查询
  • 以及快速获取数据

简单匹配

在Java中,有switch关键字,可以简化if条件判断语句。在scala中,可以使用match表达式替代。

语法结构:

变量 match { case "常量1" => 表达式1 case "常量2" => 表达式2 case "常量3" => 表达式3 case _ => 表达式4 // 默认匹配 }

示例1:

代码语言:javascript
复制
println("请输出一个词:")
// StdIn.readLine表示从控制台读取一行文本
val name = StdIn.readLine()

val result = name match {
    case "hadoop" => s"$name:大数据分布式存储和计算框架"
    case "zookeeper" => s"$name:大数据分布式协调服务框架"
    case "spark" => s"$name:大数据分布式内存计算框架..."
    case _ => s"未匹配到$name"
}

println(result)

match表达式是有返回值的,可以将match表达式对其他的变量进行赋值

守卫

在Java中,只能简单地添加多个case标签,例如:要匹配0-7,就需要写出来8个case语句。例如:

代码语言:javascript
复制
int a = 0;
switch(a) {
    case 0: a += 1;
    case 1: a += 1;
    case 2: a += 1;
    case 3: a += 1;
    case 4: a += 2;
    case 5: a += 2;
    case 6: a += 2;
    case 7: a += 2;
    default: a = 0;
}

在scala中,可以使用守卫来简化上述代码——也就是在case语句中添加if条件判断

示例:

代码语言:javascript
复制
println("请输入一个数字:")
var a = StdIn.readInt()

a match {
    case a1 if a >= 0 && a <= 3 => a += 1
    case a2 if a > 3 && a < 8 => a += 2
    case _ => a = 0
}

println(a)

匹配类型

match表达式还可以进行类型匹配。

语法格式如下:

变量 match { case 类型1变量名: 类型1 => 表达式1 case 类型2变量名: 类型2 => 表达式2 case 类型3变量名: 类型3 => 表达式3     ... case _ => 表达式4 }

示例:

代码语言:javascript
复制
    // stripMargin表示删除前面的竖线,这样看起来会显得比较整齐
    val prompt =
      """
        |0:字符串类型
        |1:整形
        |2:浮点型
        |3:Person对象类型
        |
        |请选择:
      """.stripMargin
    
    println(prompt)

    val select = StdIn.readInt()

    val selectedValue = select match {
      case 0 => "hello"
      case 1 => 1
      case 2 => 2.0
      case _ => new Person("张三")
    }


    selectedValue match {
      case x: Int => println("Int " + x)
      case y: Double => println("Double " + y)
      case z: String => println("String " + z)
      case _ => throw new Exception("not match exception")
    }

匹配集合

匹配数组

示例:

代码语言:javascript
复制
val arr = Array(1, 3, 5)
arr match {
    case Array(1, x, y) => println(x + " " + y)
    case Array(0) => println("only 0")
    case Array(0, _*) => println("0 ...")
    case _ => println("something else")
}

_:表示内容任意

*:表示数量任意

匹配列表

示例:

val lst = List(3, -1)
lst match {
    case 0 :: Nil => println("only 0")
    case x :: y :: Nil => println(s"x: $x y: $y")
    case 0 :: tail => println("0 ...")
    case _ => println("something else")
}

匹配元组

示例:

代码语言:javascript
复制
val tup = (1, 3, 7)
tup match {
    case (1, x, y) => println(s"1, $x , $y")
    case (_, z, 5) => println(z)
    case  _ => println("else")
}

变量声明中的模式匹配

在定义变量的时候,可以使用模式匹配快速获取数据。

示例:获取数组中的元素

代码语言:javascript
复制
val arr = Range(0, 10).toArray

arr.foreach(println(_))

// 使用模式匹配,获取第二个、第三个、第四个元素的值
val Array(_, x, y, z, _*) = arr

println(s"x=$x, y=$y, z=$z, ")

示例:获取List中的数据

代码语言:javascript
复制
val list = Range(0, 10).toList

// 匹配列表的第一个、第二个元素的值
val x::y::tail = list

println(s"x=$x, y=$y")

匹配样例类 - 常用

scala可以使用模式匹配来匹配样例类,从而可以快速获取样例类中的成员数据。后续,我们在开发Akka案例时,还会用到。

示例:

代码语言:javascript
复制
// 定义样例类
case class SubmitTask(id: String, name: String)
case class HeartBeat(time: Long)
case object CheckTimeOutTask

val msg1 = SubmitTask("001", "task-001")
val msg2 = HeartBeat(1000)
val msg3 = CheckTimeOutTask

val list = List(msg1, msg2, msg3)

list(2) match {
    case SubmitTask(id, name) => println(s"id=$id, name=$name")
    case HeartBeat(time) => println(s"time=$time")
    case CheckTimeOutTask => println("检查超时")
}

示例:可以使用@符号分隔case语句,用来获取用于匹配的整个示例对象

代码语言:javascript
复制
list(0) match {
    // obj表示获取用于匹配的样例对象,而id,name表示获取样例中的元素
    case  obj @ SubmitTask(id, name) => println(s"id=$id, name=$name");println(s"样例类:$obj")
    case HeartBeat(time) => println(s"time=$time")
    case CheckTimeOutTask => println("检查超时")
}

Option类型 - 重点掌握经常用

scala中,Option类型来表示可选值。这种类型的数据有两种形式:

  • Some(x):表示实际的值
  • None:表示没有值

使用Option类型,可以用来有效避免空引用(null)异常。也就是说,将来我们返回某些数据时,可以返回一个Option类型来替代。

示例:  

代码语言:javascript
复制
/**
    * 定义除法操作
    * @param a 参数1
    * @param b 参数2
    * @return Option包装Double类型
    */
  def dvi(a:Double, b:Double):Option[Double] = {
    if(b != 0) {
      Some(a / b)
    }
    else {
      None
    }
  }

  def main(args: Array[String]): Unit = {
    val result1 = dvi(1.0, 5)

    result1 match {
      case Some(x) => println(x)
      case None => println("除零异常")
    }
  }

getOrElse方法

使用getOrElse方法,当Option对应的实例是None时,可以指定一个默认值,从而避免空指针异常

示例:

代码语言:javascript
复制
val result1 = dvi(1.0, 1)

println(result1.getOrElse("除零错误"))

scala鼓励使用Option类型来封装数据,可以有效减少,在代码中判断某个值是否为null

可以使用getOrElse方法来针对None返回一个默认值

偏函数 - 理解

被包在花括号内没有match的一组case语句是一个偏函数,它是PartialFunction[A, B]的一个实例,A代表输入参数类型,B代表返回结果类型。可以理解为:偏函数是一个参数和一个返回值的函数。

示例:

代码语言:javascript
复制
// func1是一个输入参数为Int类型,返回值为String类型的偏函数
val func1: PartialFunction[Int, String] = {
    case 1 => "一"
    case 2 => "二"
    case 3 => "三"
    case _ => "其他"
}

println(func1(2))

示例:获取List中能够整除2的数字

代码语言:javascript
复制
val list = List(1,2,3,4,5,6,7)

val list2 = list.filter{
    case x if x % 2 == 0 => true
    case _ => false
}
println(list2)

正则表达式 - 了解

在scala中,可以很方便地使用正则表达式来匹配数据。

scala中提供了Regex类来定义正则表达式,要构造一个RegEx对象,直接使用String类的r方法即可。

建议使用三个双引号来表示正则表达式,不然就得对正则中的反斜杠来进行转义。

# 在字符串的后面,用.r 就可以将字符串标记为正则表达式体 val regEx = """正则表达式""".r

示例:检测是否匹配正则表达式

代码语言:javascript
复制
val emailRE = """.+@(.+)\..+""".r

val emailList = List("38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com")

// 检查邮箱是否匹配正则
val size = emailRE.findAllMatchIn(emailList(0)).size
// 如果匹配size为1,否则size为0
println(size)

示例:找出列表中的所有不合法的邮箱

代码语言:javascript
复制
// 找出列表中不合法的邮箱格式
println("不合法的邮箱为:")
emailList.filter{
    eml => emailRE.findAllIn(eml).size < 1
}.foreach {
    println(_)
}

println("------")

示例:使用正则表达式进行模式匹配,获取正则中匹配的分组

代码语言:javascript
复制
// 找到所有邮箱运营公司
println("邮箱的运营公司为")
emailList.foreach {
    case email @ emailRE(company) => println(s"$email => ${company}")
    case _ => println("未知")
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-05-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 模式匹配
    • 简单匹配
      • 守卫
        • 匹配类型
          • 匹配集合
            • 变量声明中的模式匹配
              • 匹配样例类 - 常用
                • Option类型 - 重点掌握经常用
                  • 偏函数 - 理解
                    • 正则表达式 - 了解
                    相关产品与服务
                    对象存储
                    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档