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

举报
Lansonli 发表于 2021/09/28 23:06:19 2021/09/28
【摘要】 目录 模式匹配 简单匹配 守卫 匹配类型 匹配集合 变量声明中的模式匹配 匹配样例类 - 常用 Option类型 - 重点掌握经常用 偏函数 - 理解 正则表达式 - 了解 模式匹配 scala中有一个非常强大的模式匹配机制,可以应用在很多场景: switch语句类型查询以及快速获取数据   简单...

目录

模式匹配

简单匹配

守卫

匹配类型

匹配集合

变量声明中的模式匹配

匹配样例类 - 常用

Option类型 - 重点掌握经常用

偏函数 - 理解

正则表达式 - 了解


模式匹配

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

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

 

简单匹配

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

语法结构:

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

示例1:


  
  1. println("请输出一个词:")
  2. // StdIn.readLine表示从控制台读取一行文本
  3. val name = StdIn.readLine()
  4. val result = name match {
  5.     case "hadoop" => s"$name:大数据分布式存储和计算框架"
  6.     case "zookeeper" => s"$name:大数据分布式协调服务框架"
  7.     case "spark" => s"$name:大数据分布式内存计算框架..."
  8.     case _ => s"未匹配到$name"
  9. }
  10. println(result)

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

 

守卫

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


  
  1. int a = 0;
  2. switch(a) {
  3.     case 0: a += 1;
  4.     case 1: a += 1;
  5.     case 2: a += 1;
  6.     case 3: a += 1;
  7.     case 4: a += 2;
  8.     case 5: a += 2;
  9.     case 6: a += 2;
  10.     case 7: a += 2;
  11.     default: a = 0;
  12. }

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

 

示例:


  
  1. println("请输入一个数字:")
  2. var a = StdIn.readInt()
  3. a match {
  4.     case a1 if a >= 0 && a <= 3 => a += 1
  5.     case a2 if a > 3 && a < 8 => a += 2
  6.     case _ => a = 0
  7. }
  8. println(a)

 

匹配类型

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

语法格式如下:

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

 

示例:


  
  1.     // stripMargin表示删除前面的竖线,这样看起来会显得比较整齐
  2.     val prompt =
  3.       """
  4.         |0:字符串类型
  5.         |1:整形
  6.         |2:浮点型
  7.         |3:Person对象类型
  8.         |
  9.         |请选择:
  10.       """.stripMargin
  11.     
  12.     println(prompt)
  13.     val select = StdIn.readInt()
  14.     val selectedValue = select match {
  15.       case 0 => "hello"
  16.       case 1 => 1
  17.       case 2 => 2.0
  18.       case _ => new Person("张三")
  19.     }
  20.     selectedValue match {
  21.       case x: Int => println("Int " + x)
  22.       case y: Double => println("Double " + y)
  23.       case z: String => println("String " + z)
  24.       case _ => throw new Exception("not match exception")
  25.     }

 

匹配集合

 

匹配数组

示例:


  
  1. val arr = Array(135)
  2. arr match {
  3.     case Array(1, x, y) => println(x + " " + y)
  4.     case Array(0) => println("only 0")
  5.     case Array(0, _*) => println("0 ...")
  6.     case _ => println("something else")
  7. }
  8. _:表示内容任意
  9. *:表示数量任意
  10. 匹配列表
  11. 示例:
  12. val lst = List(3-1)
  13. lst match {
  14.     case 0 :: Nil => println("only 0")
  15.     case x :: y :: Nil => println(s"x: $x y: $y")
  16.     case 0 :: tail => println("0 ...")
  17.     case _ => println("something else")
  18. }

 

匹配元组

示例:


  
  1. val tup = (137)
  2. tup match {
  3.     case (1, x, y) => println(s"1, $x , $y")
  4.     case (_, z, 5) => println(z)
  5.     case  _ => println("else")
  6. }

 

变量声明中的模式匹配

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

示例:获取数组中的元素


  
  1. val arr = Range(010).toArray
  2. arr.foreach(println(_))
  3. // 使用模式匹配,获取第二个、第三个、第四个元素的值
  4. val Array(_, x, y, z, _*) = arr
  5. println(s"x=$x, y=$y, z=$z, ")

 

示例:获取List中的数据


  
  1. val list = Range(010).toList
  2. // 匹配列表的第一个、第二个元素的值
  3. val x::y::tail = list
  4. println(s"x=$x, y=$y")

 

匹配样例类 - 常用

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

示例:


  
  1. // 定义样例类
  2. case class SubmitTask(id: String, name: String)
  3. case class HeartBeat(time: Long)
  4. case object CheckTimeOutTask
  5. val msg1 = SubmitTask("001""task-001")
  6. val msg2 = HeartBeat(1000)
  7. val msg3 = CheckTimeOutTask
  8. val list = List(msg1, msg2, msg3)
  9. list(2match {
  10.     case SubmitTask(id, name) => println(s"id=$id, name=$name")
  11.     case HeartBeat(time) => println(s"time=$time")
  12.     case CheckTimeOutTask => println("检查超时")
  13. }

 

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


  
  1. list(0) match {
  2.     // obj表示获取用于匹配的样例对象,而id,name表示获取样例中的元素
  3.     case  obj @ SubmitTask(idname) => println(s"id=$id, name=$name");println(s"样例类:$obj")
  4.     case HeartBeat(time) => println(s"time=$time")
  5.     case CheckTimeOutTask => println("检查超时")
  6. }

 

 

Option类型 - 重点掌握经常用

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

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

 

  • None:表示没有值

 

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

 

示例:  


  
  1. /**
  2.     * 定义除法操作
  3.     * @param a 参数1
  4.     * @param b 参数2
  5.     * @return Option包装Double类型
  6.     */
  7.   def dvi(a:Double, b:Double):Option[Double] = {
  8.     if(b != 0) {
  9.       Some(a / b)
  10.     }
  11.     else {
  12.       None
  13.     }
  14.   }
  15.   def main(args: Array[String]): Unit = {
  16.     val result1 = dvi(1.05)
  17.     result1 match {
  18.       case Some(x) => println(x)
  19.       case None => println("除零异常")
  20.     }
  21.   }

 

getOrElse方法

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

 

示例:


  
  1. val result1 = dvi(1.01)
  2. println(result1.getOrElse("除零错误"))

 

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

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

 

偏函数 - 理解

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

 

示例:


  
  1. // func1是一个输入参数为Int类型,返回值为String类型的偏函数
  2. val func1: PartialFunction[IntString] = {
  3.     case 1 => "一"
  4.     case 2 => "二"
  5.     case 3 => "三"
  6.     case _ => "其他"
  7. }
  8. println(func1(2))

 

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


  
  1. val listList(1,2,3,4,5,6,7)
  2. val list2 = list.filter{
  3.     case x if x % 2 == 0 => true
  4.     case _ => false
  5. }
  6. println(list2)

 

正则表达式 - 了解

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

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

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

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

 

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


  
  1. val emailRE = """.+@(.+)\..+""".r
  2. val emailList = List("38123845@qq.com""a1da88123f@gmail.com""zhansan@163.com""123afadff.com")
  3. // 检查邮箱是否匹配正则
  4. val size = emailRE.findAllMatchIn(emailList(0)).size
  5. // 如果匹配size为1,否则size为0
  6. println(size)

 

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


  
  1. // 找出列表中不合法的邮箱格式
  2. println("不合法的邮箱为:")
  3. emailList.filter{
  4.     eml => emailRE.findAllIn(eml).size < 1
  5. }.foreach {
  6.     println(_)
  7. }
  8. println("------")

 

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


  
  1. // 找到所有邮箱运营公司
  2. println("邮箱的运营公司为")
  3. emailList.foreach {
  4.     case email @ emailRE(company) => println(s"$email => ${company}")
  5.     case _ => println("未知")
  6. }

 

文章来源: lansonli.blog.csdn.net,作者:Lansonli,版权归原作者所有,如需转载,请联系作者。

原文链接:lansonli.blog.csdn.net/article/details/116724491

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。