Scala 03 —— Scala OOP Extension

news/2024/10/21 5:45:10/

在这里插入图片描述
在这里插入图片描述

Scala 2.1 —— Scala OOP Extension

一、正则

文章目录

  • Scala 2.1 —— Scala OOP Extension
      • 一、正则
          • 1.1 Java正则和Scala正则的区别
          • 1.2 Java正则和Scala正则的的基本知识点
            • Java正则
            • Scala正则
          • 1.3 练习
          • 练习一:使用正则表达式解析日志
            • 方法一:使用`findAllMatchIn`方法提取出所有符合正则且可按组匹配的对象构成一个迭代器,后通过`map`方法将每一行中符合的部分提取出来构成元组。
            • 方法二:使用`collect`方法在传入的偏函数中构造模式匹配,将匹配的部分提取出来构成元组
          • 练习二:提取字符串的每组数据
      • 二、隐式类
      • 三、异常
          • 3.1.Java的基本异常处理结构
            • `try-catch-finally`
            • `try-with-resources`
            • 对比
          • 3.2.Scala的异常处理机制
            • Option类型
            • Either类型
            • Try类型
            • 值获取方式
            • catch的模式匹配
          • 3.3.Scala的异常控制工具
            • allCatch工具
            • failAsValue工具
      • 四、类型信息处理
          • 4.1 定义类和子类
          • 4.2 实例化和使用
          • 4.3 类型判断和检查

1.1 Java正则和Scala正则的区别
  • Java调用的主体是字符串,Scala调用的主体是正则对象
1.2 Java正则和Scala正则的的基本知识点
Java正则
public static void main(String[] args) {// 匹配String regex = "\\d+";String content1 = "123";System.out.println(content1.matches(regex)); // true, 因为"123"完全由数字组成// 替换String content2 = "123,avc,$%#";System.out.println(content2.replaceAll(regex, "")); // ",avc,$%#", 将所有数字替换为空字符串System.out.println(content2.replaceFirst(regex, "")); // ",avc,$%#", 将第一个数字序列替换为空字符串// 分割String content3 = "123,asd,#$,456";System.out.println(content3.split("[^0-9]+").toString()); // 打印的是数组对象的内存地址, 如"[Ljava.lang.String;@15db9742"// 分组final Pattern cp1 = Pattern.compile("([a-z]+.*?\\d+)");final Pattern cp2 = Pattern.compile("([a-z]+):(\\d+)");String scores = "java:88,mysql:a99,hadoop:82,spark:91";final Matcher mt1 = cp1.matcher(scores);while (mt1.find()){final String score = mt1.group(0);final Matcher mt2 = cp2.matcher(score);if(mt2.find()){System.out.println(mt2.group(1) + "->" + mt2.group(2)); // "java->88", "hadoop->82", "spark->91"}}
}
Scala正则
scala">// 初始化正则表达式
val regexStr: String = "\\d+"
val regex: Regex = regexStr.r// 字符串匹配
val content = "123"
println(content.matches(regexStr)) // 输出:true// 字符串分割
val content4 = "123,87,xy,921"
content4.split("[^0-9]+").foreach(println) // 输出分割后的数字:123, 87, 921// 字符串替换
// 替换字符串中的第一个匹配项:
val content3 = "123,87,xy,921"
println(regex.replaceFirstIn(content3, "66")) // 输出:66,87,xy,921// 替换所有符合正则的对象,匹配到就替换,没有匹配到就不替换,返回类型是Option[String]
println(regex.replaceSomeIn(content3, mat => Some((mat.group(0).toInt + 1).toString)))// 替换所有符合正则的对象,匹配到就替换,没有匹配到就不替换,返回类型是String
println(regex.replaceAllIn(content3, mat => (mat.group(0).toInt + 1).toString))// 模式匹配
val content = "123,456,789"
val regex = "(\\d+),(\\d+),(\\d+)".r
println(content match {case regex(a, b, c) => (a.toInt + 1, b.toInt + 1, c.toInt + 1)
})// 如果content2符合regex2的模式,regex2(a,b,c,d)会提取四个字符串,并且存放到变量a,b,c,d中;匹配成功后,将这四个字符串变量转换为整数+1。// 分组
val pat = "([a-zA-Z]+):(\\d+)".r // 边界(粗略提取整体)
val patIn = "([a-zA-Z]+):(\\d+)".r // 正则构成(提取细则)
val scores = "java:88,mysql:99,hadoop:82,spark:91";// 提取第一个符合正则的对象
val opt: Option[String] = pat.findFirstIn(scores)
println(opt.get) // java:88
// 提取所有符合正则的对象
val it: Regex.MatchIterator = pat.findAllIn(scores)
println(it.mkString(","))  // 输出:java:88,mysql:99,hadoop:82,spark:91// 提取第一个符合正则的对象,且该对象可以按组匹配
val mat: Option[Regex.Match] = patIn.findFirstMatchIn(scores)
val str: String = mat.get.group(1)
val str2: String = mat.get.group(2)
println(str + ":" + str2)// 输出:java:88// 提取出所有符合正则且可按组匹配的对象构成一个迭代器
val mats: Iterator[Regex.Match] = patIn.findAllMatchIn(scores)
mats.map(m=>{val subject: String = m.group(1)val score: String = m.group(2)(subject,score)
}).foreach(println)// 依次输出:(java,88), (mysql,99), (hadoop,82), (spark,91)
1.3 练习
练习一:使用正则表达式解析日志

现有如下日志信息,请使用scala正则表达式解析如下信息:
日志级别
日期
请求URI

scala">INFO 2016-07-25 requestURI:/c?app=0&p=1&did=18005472&industry=469&adid=31
INFO 2016-07-26 requestURI:/c?app=0&p=2&did=18005473&industry=472&adid=31
INFO 2016-07-27 requestURI:/c?app=0&p=1&did=18005474&industry=488&adid=32
方法一:使用findAllMatchIn方法提取出所有符合正则且可按组匹配的对象构成一个迭代器,后通过map方法将每一行中符合的部分提取出来构成元组。
scala">val logs = "INFO 2016-07-25 requestURI:/c?app=0&p=1&did=18005472&industry=469&adid=31\n" +"INFO 2016-07-26 requestURI:/c?app=0&p=2&did=18005473&industry=472&adid=31\n" +"INFO 2016-07-27 requestURI:/c?app=0&p=1&did=18005474&industry=488&adid=32"
val pat = "(INFO|WARN|ERROR) ([0-9]{4}-[0-9]{2}-[0-9]{2}) requestURI:(.*)".r
val it = pat.findAllMatchIn(logs)
it.map(m=>{val level: String = m.group(1)val date: String = m.group(2)val uri: String = m.group(3)(level,date,uri)
}).foreach(println)
/* 输出:
(INFO,2016-07-25,/c?app=0&p=1&did=18005472&industry=469&adid=31)
(INFO,2016-07-26,/c?app=0&p=2&did=18005473&industry=472&adid=31)
(INFO,2016-07-27,/c?app=0&p=1&did=18005474&industry=488&adid=32)
*/
方法二:使用collect方法在传入的偏函数中构造模式匹配,将匹配的部分提取出来构成元组
scala">val regex = "(INFO|WARN|ERROR) (\\d{4}-\\d{2}-\\d{2}) requestURI:(.*)".r
Array("INFO 2016-07-25 requestURI:/c?app=0&p=1&did=18005472&industry=469&adid=31","INFO 2016-07-26 requestURI:/c?app=0&p=2&did=18005473&industry=472&adid=31","INFO 2016-07-27 requestURI:/c?app=0&p=1&did=18005474&industry=488&adid=32","WRONG 2016-07-26 requestURI:/c?app=0&p=2&did=18005473&industry=472&adid=31"
).collect({case regex(level,date,uri) => (level,date,uri)
}).foreach(println)/* 输出:
(INFO,2016-07-25,/c?app=0&p=1&did=18005472&industry=469&adid=31)
(INFO,2016-07-26,/c?app=0&p=2&did=18005473&industry=472&adid=31)
(INFO,2016-07-27,/c?app=0&p=1&did=18005474&industry=488&adid=32)
*/
练习二:提取字符串的每组数据
scala">val scores = "java:88,mysql:99,hadoop:82,spark:91"
val regex: Regex = "([a-z]+):(\\d+)".r
val it: Iterator[Regex.Match] = regex.findAllMatchIn(scores)
it.foreach(mat => println(mat.group(1),mat.group(2).toInt))
/*
(java,88)
(mysql,99)
(hadoop,82)
(spark,91)
*/
scala">val scores = "java:88,mysql:99,hadoop:82,spark:91"
val pat1: Pattern = Pattern.compile("([a-z]+.*?\\d+)")
val pat2: Pattern = Pattern.compile("([a-z]+):(\\d+)")
val mat1: Matcher = pat1.matcher(scores)
while(mat1.find()){val score: String = mat1.group(0)val mat2: Matcher = pat2.matcher(score)if(mat2.find()){println((mat2.group(1), mat2.group(2)))}
}

二、隐式类

隐式类允许你向已存在的类型添加新的方法,是一种便捷的方式在不修改源代码的情况下扩展类的功能。

  1. 定义
    • 隐式类通常用于扩展某个类型的功能。它们通过隐式转换将原始类型转换为提供额外方法的新类型。
  2. 约束条件
    • 位置:隐式类必须定义在类、trait或者对象(包括单例对象和包对象)内部。
    • 构造器参数:隐式类的主构造器==必须且只能有一个非隐式参数。==这个参数是被扩展的类型,隐式类将为这个类型添加新的功能。
    • 非case类:==隐式类不能是case类。==Scala的case类用于模式匹配和简化数据类的创建,但隐式类用途不同,它主要用于类型转换和扩展功能。
    • 唯一性:在定义隐式类的同一作用域内,不能有与之同名的其他方法、成员或对象。
scala">// 字符串的方法扩展,而在 Java 中 String 是final的,无法扩展
implicit class StrExt(str:String){def incr() = str.map(c=>(c+1).toChar)def isEmail = str.matches("\\w+@[a-z0-9]{2,10}\\.(com(.cn)?|cn|edu|org)")
}val a:String = "12665473@qq.com"
val incr: String = a.incr
val isEmail: Boolean = a.isEmail

三、异常

3.1.Java的基本异常处理结构
try-catch-finally
private static void close(AutoCloseable...acs){for (AutoCloseable ac : acs) {if (Objects.nonNull(ac)) {try {ac.close();} catch (Exception e) {e.printStackTrace();}}}
}try{// 可能抛出异常的代码块BufferedReader reader = new BufferedReader(new FileReader("test.txt"));System.out.println(reader.readLine());
} catch(IOException ex) {// 异常的捕获和处理System.err.println("An IOException occurred: " + ex.getMessage());
} finally{// 无论是否发生异常,都会执行的代码块,通常用于释放资源close(reader);
}
try-with-resources
try (BufferedWriter writer = new BufferedWriter(new FileWriter("test.txt"))) {// 使用资源,该资源必须extends AutoCloseable// try块中的`BufferedWriter`在代码块执行完毕后会自动关闭,不需要再通过finally关闭资源writer.write("Hello World");
} catch (IOException ex) {// 异常的捕获和处理System.err.println("An IOException occurred: " + ex.getMessage());
}
对比

try-catch-finallyfinally不仅可以关闭资源,还可以用于执行其他代码块。

try-with-resources资源会立即被关闭,InputStream,OutputStream,Reader,Writer等均实现了该接口。

try-with-resources优先于try-catch-finally,因为可能会存在finally延迟。

3.2.Scala的异常处理机制

3.2.1 异常数据类型

Option类型

使用Option类型可以在函数无法返回有效结果时,返回None,而不是抛出异常。

scala">def divideOption(a:Int,b:Int):Option[Int] = {try {Some(a/b)}catch {case _ : ArithmeticException => None}
}
Either类型

Either类型通常用于函数可能返回两种类型的结果,其中Left通常用于错误或异常,Right用于正常值。

Either[String, Int]需要包含两种数据类型的原因是需要同时兼容``Right[Nothing,Int]Left[String,Nothing]的类型。

scala">def divideEither(a: Int, b: Int): Either[String, Int] = {try {Right(a / b)}:Right[Nothing,Int] catch {case _: ArithmeticException => Left("divide by zero"):Left[String,Nothing]}
}
Try类型

Try 是一个代表可能会成功或失败的操作的容器类型。Success表示操作成功,Failure表示操作失败。

Failure需要一个Throwable对象作为参数。

scala">def divideTry(a: Int, b: Int): Try[Int] = {try {Success(a / b)} catch {case _: ArithmeticException => Failure(new Exception("divide by zero"))}
}
值获取方式

Option 类型:getOrElse()

EitherTry 类型:模式匹配

scala">val either: Either[Int, String] = Left(404)val errorInfo = either match {case Left(err) => s"发生错误,错误码:$err"case Right(value) => s"操作成功,结果为:$value"
}
// 这会返回:"发生错误,错误码:404"
scala">import scala.util.{Try, Success, Failure}val attempt = Try { Integer.parseInt("abc") }val result = attempt match {case Success(value) => s"转换成功,结果为:$value"case Failure(ex) => s"转换失败,错误信息:${ex.getMessage}"
}
// 这会返回:"转换失败,错误信息:For input string: "abc""

3.2.2 模式匹配

catch的模式匹配
scala">try {// 可能抛出异常的代码块val result = 10 / 0
} catch {// 捕获异常的格式是:case e:XxxException => ...case ex: ArithmeticException => println("ArithmeticException occurred")case ex: NullPointerException => println("NullPointerException occurred")case ex: Exception => println("Other exception occurred: " + ex.getMessage)
}
3.3.Scala的异常控制工具
allCatch工具
  • opt: 将异常转换为Option
  • withTry: 将结果包装在Try
  • either: 将异常或结果包装在Either
scala">import scala.util.control.Exception.allCatchdef divideOpt(a: Int, b: Int) = allCatch.opt(a / b)
def divideWithTry(a: Int, b: Int) = allCatch.withTry(a / b)
def divideEither(a: Int, b: Int) = allCatch.either(a / b)
failAsValue工具
  • failAsValue允许你指定某种异常类型,并在捕获到该异常时返回一个默认值。
scala">import scala.util.control.Exception.failAsValuedef divideFail(a: Int, b: Int) = failAsValue(classOf[ArithmeticException])(-1)(a / b)

四、类型信息处理

4.1 定义类和子类
scala">case class Text(author: String, title: String, price: Float)class TextSon(level: String,override val author: String,override val title: String,override val price: Float)
extends Text(author, title, price) {val _level: String = leveloverride def toString() = s"TextSon{${super.toString}, ${_level}}"
}

添加新的属性后如何重新toString()方法?

scala">override def toString() = s"TextSon{${super.toString}, ${_level}}"
4.2 实例化和使用
scala">val obj: Text = new TextSon("TOP", "The Wild Roaring", "张培元", 86.32f)
4.3 类型判断和检查

进行类型判断,检查obj是否是TextSon类型的实例

scala">val isIns: Boolean = obj.isInstanceOf[TextSon]

进行类型转换,需要通过allCatch.opt()进行异常处理

scala">val safeSon: Option[TextSon] = allCatch.opt(obj.asInstanceOf[TextSon])
println(opt.getOrElse("转换失败"))

在这里插入图片描述


http://www.ppmy.cn/news/1442246.html

相关文章

Mac安装flutter环境

好记性不如烂笔头,之前出现文章用的后面再访问就没了,不如自己保存备份一份,哈哈 MAC电脑安装flutter环境 一,获取Flutter SDK 去flutter官网下载其最新可用的安装包 地址:https://flutter.dev/docs/development/tools/sdk/releases?tabmacos#macos …

踏上R语言之旅:解锁数据世界的神秘密码(三)

多元相关与回归分析及R使用 文章目录 多元相关与回归分析及R使用一.变量间的关系分析1.两变量线性相关系数的计算2.相关系数的假设检验 二.一元线性回归分析的R计算三、回归系数的假设检验总结 一.变量间的关系分析 变量间的关系及分析方法如下: 1.两变量线性相关…

Python-turtle函数

一、绘图相关的函数 1.绘图坐标系 turtle.setup(width,height,startx,starty):用于设置主窗体的大小和位置 (1)width:窗口宽度 如果值是整数,那么width表示像素值;如果值是小数,那么表示窗口宽度与屏幕的比例 (2)height:窗口高度…

每日OJ题_其它背包问题①_力扣474. 一和零(二维费用01背包)

目录 力扣474. 一和零 解析代码 代码优化 力扣474. 一和零 474. 一和零 难度 中等 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&…

C语言-atoi和atof函数的使用

人生应该树立目标,否则你的精力会白白浪费。💓💓💓 目录 •🌙知识回顾 🍋知识点一:atoi函数的使用和实现 • 🌰1.函数介绍 • 🌰2.代码演示 • 🌰3.atoi函数的…

PotatoPie 4.0 实验教程(24) —— FPGA实现摄像头图像中心差分变换

为什么要对图像进行中心差分变换? 对图像进行中心差分变换的主要目的是计算图像中每个像素点的梯度。梯度在图像处理中是一个非常重要的概念,它可以用来描述图像中灰度变化的快慢和方向,常用于边缘检测、特征提取和图像增强等任务中。 具体…

HTTP与HTTPS 对比,区别详解(2024-04-25)

一、简介 HTTP(超文本传输协议,Hypertext Transfer Protocol)是一种用于从网络传输超文本到本地浏览器的传输协议。它定义了客户端与服务器之间请求和响应的格式。HTTP 工作在 TCP/IP 模型之上,通常使用端口 80。 HTTPS&#xf…

element -ui 横向时间轴,时间轴悬浮对应日期

效果&#xff1a; <el-tabs v-model"activeName" type"card" tab-click"handleClick"><el-tab-pane label"周期性巡视" name"zqxxs" key"zqxxs" class"scrollable-tab-pane"><div v-if…