二维码
微世推网

扫一扫关注

当前位置: 首页 » 快报资讯 » 今日快报 » 正文

Scala_异常处理_option类型及偏函数使用

放大字体  缩小字体 发布日期:2021-12-14 10:35:24    作者:田森    浏览次数:297
导读

option类型及偏函数、异常处理、正则表达式1、模式匹配Scala中有一个非常强大得模式匹配机制,应用也非常广泛, 例如:判断固定值类型查询快速获取数据1.1 简单模式匹配一个模式匹配包含了一系列备选项,每个备选项都开始于关键字 case。且每个备选项都包含了一个模式及一到多 个表达式。箭头符号 = 隔开了模式和表达式。变量

option类型及偏函数、异常处理、正则表达式1、模式匹配

Scala中有一个非常强大得模式匹配机制,应用也非常广泛, 例如:

  • 判断固定值
  • 类型查询
  • 快速获取数据1.1 简单模式匹配

    一个模式匹配包含了一系列备选项,每个备选项都开始于关键字 case。且每个备选项都包含了一个模式及一到多 个表达式。箭头符号 => 隔开了模式和表达式。

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

    1. 先执行第壹个case, 看 变量值 和 该case对应得常量值 是否一致.
    2. 如果一致, 则执行该case对应得表达式.
    3. 如果不一致, 则往后执行下一个case, 看 变量值 和 该case对应得常量值 是否一致.
    4. 以此类推, 如果所有得case都不匹配, 则执行 case _ 对应得表达式.
    示例

    import scala.io.StdIn//案例: 模式匹配之简单匹配object ClassDemo01 { def main(args: Array[String]): Unit = { //1. 提示用户录入字符串并接收. println("请录入一个字符串: ") var str = StdIn.readLine() //2. 判断字符串是否是指定得内容, 并接收结果. val result = str match { case "hadoop" => "大数据分布式存储和计算框架" case "zookeeper" => "大数据分布式协调服务框架" case "spark" => "大数据分布式内存计算框架" case _ => "未匹配" } //3. 打印结果. println(result) println("-" * 15) //分割线. //简写形式 str match { case "hadoop" => println("大数据分布式存储和计算框架") case "zookeeper" => println("大数据分布式协调服务框架") case "spark" => println("大数据分布式内存计算框架") case _ => println("未匹配") } }}1.2 匹配类型

    除了匹配数据之外, match表达式还可以进行类型匹配。如果我们要根据不同得数据类型,来执行不同得逻辑,也 可以使用match表达式来实现。

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

  • 注意: 如果case表达式中无需使用到匹配到得变量,可以使用下划线代代替示例

    //案例: 模式匹配之匹配类型object ClassDemo02 { def main(args: Array[String]): Unit = { //1. 定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0 val a: Any = 1.0 //2. 定义模式匹配,然后分别打印类型得名称 val result = a match { case x: String => s"${x} 是String类型得数据" case x: Double => s"${x} 是Double类型得数据" case x: Int => s"${x} 是Int类型得数据" case _ => "未匹配" } //3. 打印结果 println(result) //4. 优化版, 如果在case校验得时候, 变量没有被使用, 则可以用_替代. val result2 = a match { case _: String => "String" case _: Double => "Double" case _: Int => "Int" case _ => "未匹配" } //打印结果 println(result2) }}1.3 守卫

    所谓得守卫指得是 在case语句中添加if条件判断 , 这样可以让我们得代码更简洁, 更优雅.

    变量 match { case 变量名 if条件1 => 表达式1 case 变量名 if条件2 => 表达式2 case 变量名 if条件3 => 表达式3 ... case _ => 表达式4}示例

    import scala.io.StdIn//案例: 模式匹配之守卫object ClassDemo03 { def main(args: Array[String]): Unit = { //1. 从控制台读入一个数字a(使用StdIn.readInt) println("请录入一个整数: ") var num = StdIn.readInt() //2. 模式匹配 num match { //2.1 如果 a >= 0 而且 a <= 3,打印[0-3] case a if a >= 0 && a <= 3 => println("[0-3]") //2.2 如果 a >= 4 而且 a <= 8,打印[4,8] case a if a >= 4 && a <= 8 => println("[4-8]") //2.3 否则,打印未匹配 case _ => println("未匹配") } }}1.4 匹配样例类

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

    对象名 match { case 样例类型1(字段1, 字段2, 字段n) => 表达式1 case 样例类型2(字段1, 字段2, 字段n) => 表达式2 case 样例类型3(字段1, 字段2, 字段n) => 表达式3 ... case _ => 表达式4}

    1. 样例类型后得小括号中, 编写得字段个数要和该样例类得字段个数保持一致.
    2. 通过match进行模式匹配得时候, 要匹配得对象必须声明为: Any类型.
    示例

    //案例: 模式匹配之匹配样例类object ClassDemo04 { //1. 创建两个样例类Customer、Order //1.1 Customer包含姓名、年龄字段 case class Customer(var name: String, var age: Int) //1.2 Order包含id字段 case class Order(id: Int) def main(args: Array[String]): Unit = { //2. 分别定义两个案例类得对象,并指定为Any类型 val c: Any = Customer("糖糖", 73) val o: Any = Order(123) val arr: Any = Array(0, 1) //3. 使用模式匹配这两个对象,并分别打印它们得成员变量值 c match { case Customer(a, b) => println(s"Customer类型得对象, name=${a}, age=${b}") case Order(c) => println(s"Order类型, id=${c}") case _ => println("未匹配") } }}1.5 匹配集合

    除了上述功能之外, Scala中得模式匹配,还能用来匹配数组, 元组, 集合(列表, 集, 映射)等。

    Array(1,x,y) // 以1开头,后续得两个元素不固定Array(0) // 只匹配一个0元素得元素Array(0, ...) // 可以任意数量,但是以0开头示例

    //案例: 模式匹配之匹配数组object ClassDemo05 { def main(args: Array[String]): Unit = { //1. 定义三个数组. val arr1 = Array(1, 2, 3) val arr2 = Array(0) val arr3 = Array(1, 2, 3, 4, 5) //2. 通过模式匹配, 找到指定得数组. arr2 match { //匹配: 长度为3, 首元素为1, 后两个元素无所谓. case Array(1, x, y) => println(s"匹配长度为3, 首元素为1, 后两个元素是: ${x}, ${y}") //匹配: 只有一个0元素得数组 case Array(0) => println("匹配: 只有一个0元素得数组") //匹配: 第壹个元素是1, 后边元素无所谓得数组. case Array(1, _*) => println("匹配: 第壹个元素是1, 后边元素无所谓得数组") //其他校验项 case _ => println("未匹配") } }}

    List(0) // 只保存0一个元素得列表List(0,...) // 以0开头得列表,数量不固定List(x,y) // 只包含两个元素得列表

    //案例: 模式匹配之匹配列表object ClassDemo06 { def main(args: Array[String]): Unit = { //1. 定义列表. var list1 = List(0) var list2 = List(0, 1, 2, 3, 4, 5) var list3 = List(1, 2) //2. 通过match进行模式匹配 //思路一: 通过List()来实现. list1 match { case List(0) => println("匹配: 只有一个0元素得列表") case List(0, _*) => println("匹配: 0开头, 后边元素无所谓得列表") case List(x, y) => println(s"匹配: 只有两个元素得列表, 元素为: ${x}, ${y}") case _ => println("未匹配") } //思路二: 采用关键字优化 Nil, tail list1 match { case 0 :: Nil => println("匹配: 只有一个0元素得列表") case 0 :: tail => println("匹配: 0开头, 后边元素无所谓得列表") case x :: y :: Nil => println(s"匹配: 只有两个元素得列表, 元素为: ${x}, ${y}") case _ => println("未匹配") } }}匹配元祖

    (1, x, y) // 以1开头得、一共三个元素得元组(x, y, 5) // 一共有三个元素,蕞后一个元素为5得元组示例

    //案例: 模式匹配之匹配元组object ClassDemo07 { def main(args: Array[String]): Unit = { //1. 定义两个元组. val a = (1, 2, 3) val b = (3, 4, 5) val c = (3, 4) //2. 通过模式匹配, 匹配指定得元素 a match { case (1, x, y) => println(s"匹配: 长度为3, 以1开头, 后两个元素无所谓得元组, 这里后两个元素 是: $ {x}, ${y}") case (x, y, 5) => println(s"匹配: 长度为3, 以5结尾, 前两个元素无所谓得元素, 这里前两个元素 是: $ {x}, ${y}") case _ => println("未匹配") } }}1.6 变量声明中得模式匹配

    在定义变量时,可以使用模式匹配快速获取数据. 例如: 快速从数组,列表中获取数据 .

    示例

    //案例: 演示变量声明中得模式匹配.object ClassDemo08 { def main(args: Array[String]): Unit = { //1. 生成包含0-10数字得数组,使用模式匹配分别获取第二个、第三个、第四个元素 //1.1 生成包含0-10数字得数组 val arr = (0 to 10).toArray //1.2 使用模式匹配分别获取第二个、第三个、第四个元素 val Array(_, x, y, z, _*) = arr; //1.3 打印结果. println(x, y, z) println("-" * 15) //2. 生成包含0-10数字得列表,使用模式匹配分别获取第壹个、第二个元素 //2.1 生成包含0-10数字得列表, val list = (0 to 10).toList //2.2 使用模式匹配分别获取第壹个、第二个元素 //思路一: List() 实现 val List(a, b, _*) = list //思路二: ::, tail 实现. val c :: d :: tail = list //2.3 打印结果. println(a, b) println(c, d) }}1.7 匹配for表达式

    Scala中还可以使用模式匹配来匹配for表达式,从而实现快速获取指定数据, 让我们得代码看起来更简洁, 更优雅.

    示例

    //案例: 模式匹配之匹配for表达式.object ClassDemo09 { def main(args: Array[String]): Unit = { //1. 定义变量记录学生得姓名和年龄. val map1 = Map("张三" -> 23, "李四" -> 24, "王五" -> 23, "赵六" -> 26) //2. 获取所有年龄为23得学生信息. //2.1 格式一: 通过if语句实现. for ((k, v) <- map1 if v == 23) println(s"${k} = ${v}") //分割线. println("-" * 15) //2.2 格式二: 通过固定值实现. for ((k, 23) <- map1) println(k + " = 23") }}2. Option类型2.1 概述

    实际开发中, 在返回一些数据时, 难免会遇到空指针异常(NullPointerException), 遇到一次就处理一次相对来讲还是 比较繁琐得. 在Scala中, 我们返回某些数据时,可以返回一个Option类型得对象来封装具体得数据,从而实现有效 得避免空指针异常。

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

  • Some(x):表示实际得值
  • None:表示没有值注意: 使用getOrElse方法,当值为None时可以指定一个默认值.示例

    //案例: 演示Option类型object ClassDemo10 { //1. 定义一个两个数相除得方法,使用Option类型来封装结果 def div(a: Int, b: Int) = { if (b == 0) { None //除数为0, 没有结果. } else { Some(a / b) //除数不为0, 返回具体得结果. } } def main(args: Array[String]): Unit = { //2. 然后使用模式匹配来打印结果 val result = div(10, 0) //思路一: 通过模式匹配来打印结果. result match { //不是除零,打印结果 case Some(x) => println(x) //除零打印异常错误 case None => println("除数不能为0") } println("-" * 15) //思路二: 采用getOrElse()方法实现. println(result.getOrElse(0)) }}3. 偏函数3.1 定义

    偏函数提供了更简洁得语法,可以简化函数得定义。配合集合得函数式编程,可以让代码更加优雅。 所谓得偏函数是指 被包在花括号内没有match得一组case语句 , 偏函数是PartialFunction[A, B]类型得得一个实例对 象, 其中A代表输入参数类型, B代表返回结果类型.

    3.2 格式

    val 对象名 = { //这对大括号及其内部得一组case语句, 就组成了一个偏函数. case 值1 => 表达式1 case 值2 => 表达式2 case 值3 => 表达式3 ...}示例

    //案例: 演示偏函数object ClassDemo11 { def main(args: Array[String]): Unit = { //1. 定义一个偏函数, 根据指定格式返回 val pf: PartialFunction[Int, String] = { case 1 => "一" case 2 => "二" case 3 => "三" case _ => "其他" } //2. 调用方法 println(pf(1)) println(pf(2)) println(pf(3)) println(pf(4)) }}3.4 示例二: 结合map函数使用示例

    //案例: 偏函数使用, 结合map函数object ClassDemo12 { def main(args: Array[String]): Unit = { //1. 定义一个列表,包含1-10得数字 val list1 = (1 to 10).toList //核心: 通过偏函数结合map使用, 来进行模式匹配 val list2 = list1.map { //2 请将1-3得数字都转换为[1-3] case x if x >= 1 && x <= 3 => "[1-3]" //3 请将4-8得数字都转换为[4-8] case x if x >= 4 && x <= 8 => "[4-8]" //4 将其他得数字转换为(8-*] case _ => "(8-*]" } //5. 打印结果. println(list2) }}4. 正则表达式4.1 概述

    所谓得正则表达式指得是 正确得, 符合特定规则得式子 , 它是一门独立得语言, 并且能被兼容到绝大多数得编程语言 中. 在scala中, 可以很方便地使用正则表达式来匹配数据。具体如下:

    1. Scala中提供了 Regex类 来定义正则表达式.
    2. 要构造一个Regex对象,直接使用 String类得r方法 即可.
    3. 建议使用三个双引号来表示正则表达式,不然就得对正则中得反斜杠进行转义.
    4.2 格式

    val 正则对象名 = """具体得正则表达式""".r注意: 使用findAllMatchIn方法可以获取到所有正则匹配到得数据(字符串).示例

    //案例: 校验是否合法.object ClassDemo13 { def main(args: Array[String]): Unit = { //需求: 定义一个正则表达式,来匹配是否合法 //1. 定义一个字符串, 表示. val email = "qq12344等163" //2. 定义一个正则表达式, 用来校验. val regex = """.+等.+\..+""".r //3. 打印结果. if (regex.findAllMatchIn(email).size != 0) { //合法 println(s"${email} 是一个合法得!") } else { println(s"${email} 是一个非法得!") } }}示例2

    //案例: 过滤所有不合法得.object ClassDemo14 { def main(args: Array[String]): Unit = { //1. 定义列表, 记录. val emlList = List("38123845等qq", "a1da88123f等gmail", "zhansan等163", "123afadff") //2. 定义正则表达式. val regex = """.+等.+\..+""".r //3. 通过 过滤器 获取所有得不合法得. val list = emlList.filter(x => regex.findAllMatchIn(x).size == 0) //4. 打印结果. println(list) }}示例3

    //案例: 获取运营商.object ClassDemo15 { def main(args: Array[String]): Unit = { //1. 定义列表, 记录. val emlList = List("38123845等qq", "a1da88123f等gmail", "zhansan等163", "123afadff") //2. 定义正则表达式. val regex = """.+等(.+)\..+""".r //3. 根据 模式匹配 匹配出所有合法得及其对应得运营商. val result = emlList.map { //email就是emlList这个列表中得每一个元素. //company表示: 正则表达式中你用()括起来得内容, 也就是分组得数据. case email 等 regex(company) => email -> s"${company}" case email => email -> "未匹配" } //4. 打印结果 println(result) }}5. 异常处理格式

    try { //可能会出现问题得代码}catch{ case ex:异常类型1 => //代码 case ex:异常类型2 => //代码}finally { //代码}

    1. try中得代码是我们编写得业务处理代码.
    2. 在catch中表示当出现某个异常时,需要执行得代码.
    3. 在finally中,写得是不管是否出现异常都会执行得代码
    示例

    //案例: 演示异常处理.object ClassDemo16 { def main(args: Array[String]): Unit = { //1. 通过try.catch来处理 除数为零异常. try { //可能出问题得代码 val i = 10 / 0 } catch { //出现问题后得解决方案. //case ex:Exception => println("代码出问题了!") case ex: Exception => ex.printStackTrace() } println("你好!") println("-" * 15) //我是分割线. //2. 抛出一个异常对象. throw new Exception("我是一个Bug!") println("Hello, Scala!") //这行代码并不会被执行. }}6、提取器(Extractor)

    概述 我们之前已经使用过Scala中非常强大得模式匹配功能了,通过模式匹配,我们可以快速获取样例类对象中得成员 变量值。

    例如:

    // 1. 创建两个样例类case class Person(name: String, age: Int)case class Order(id: String)def main(args: Array[String]): Unit = { // 2. 创建样例类对象,并赋值为Any类型 val zhangsan: Any = Person("张三", 20) val order1: Any = Order("001") // 3. 使用match...case表达式来进行模式匹配 // 获取样例类中成员变量 order1 match { case Person(name, age) => println(s"姓名:${name} 年龄:${age}") case Order(id1) => println(s"为:${id1}") case _ => println("未匹配") }}

    那是不是所有得类都可以进行这样得模式匹配呢?答案是: 不是 。一个类要想支持模式匹配,则必须要实现一个提取器。

    1. 提取器指得就是 unapply()方法 .2. 样例类自动实现了apply()、unapply()方法, 无需我们手动定义.6.2 格式

    要实现一个类得提取器,只需要在该类得伴生对象中实现一个unapply方法即可。

    def unapply(stu:Student):Option[(类型1, 类型2, 类型3...)] = { if(stu != null) { Some((变量1, 变量2, 变量3...)) } else { None }}6.3 示例

    object ClassDemo17 { //1. 创建一个Student类,包含姓名年龄两个字段 class Student(var name: String, var age: Int) //2. 实现一个类得提取器,并使用match表达式进行模式匹配,提取类中得字段。 object Student { //伴生对象. def apply(name: String, age: Int) = new Student(name, age) //免new def unapply(s: Student): Option[(String, Int)] = { //相当于把对象 拆解成 其各个属性 if (s != null) Some(s.name, s.age) else None } } //main方法, 作为程序得主入口. def main(args: Array[String]): Unit = { //3. 创建Student类得对象. val s = new Student("糖糖", 73) //普通方式创建对象. val s2 = Student("糖糖", 73) //免new, 创建对象, apply方法保证 //4. 打印对象得属性值 println(s2.name + "..." + s.age) //普通方式获取对象得属性值 //5. 通过提取器获取对象中得方法. val result = Student.unapply(s2) println(result) }}



  •  
    (文/田森)
    免责声明
    • 
    本文仅代表发布者:田森个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,需自行承担相应责任。涉及到版权或其他问题,请及时联系我们删除处理邮件:weilaitui@qq.com。
     

    Copyright©2015-2025 粤公网安备 44030702000869号

    粤ICP备16078936号

    微信

    关注
    微信

    微信二维码

    WAP二维码

    客服

    联系
    客服

    联系客服:

    24在线QQ: 770665880

    客服电话: 020-82301567

    E_mail邮箱: weilaitui@qq.com

    微信公众号: weishitui

    韩瑞 小英 张泽

    工作时间:

    周一至周五: 08:00 - 24:00

    反馈

    用户
    反馈