Scala 03 —— Scala OOP Extension

news2024/9/30 13:19:09

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

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 类型判断和检查
          • 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正则
// 初始化正则表达式
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

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方法将每一行中符合的部分提取出来构成元组。
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方法在传入的偏函数中构造模式匹配,将匹配的部分提取出来构成元组
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)
*/
练习二:提取字符串的每组数据
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)
*/
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类用于模式匹配和简化数据类的创建,但隐式类用途不同,它主要用于类型转换和扩展功能。
    • 唯一性:在定义隐式类的同一作用域内,不能有与之同名的其他方法、成员或对象。
// 字符串的方法扩展,而在 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,而不是抛出异常。

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]的类型。

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对象作为参数。

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

Option 类型:getOrElse()

EitherTry 类型:模式匹配

val either: Either[Int, String] = Left(404)

val errorInfo = either match {
  case Left(err) => s"发生错误,错误码:$err"
  case Right(value) => s"操作成功,结果为:$value"
}
// 这会返回:"发生错误,错误码:404"
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的模式匹配
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
import scala.util.control.Exception.allCatch

def 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允许你指定某种异常类型,并在捕获到该异常时返回一个默认值。
import scala.util.control.Exception.failAsValue

def divideFail(a: Int, b: Int) = failAsValue(classOf[ArithmeticException])(-1)(a / b)

四、类型信息处理

4.1 定义类和子类
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 = level
    override def toString() = s"TextSon{${super.toString}, ${_level}}"
}

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

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

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

val isIns: Boolean = obj.isInstanceOf[TextSon]

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

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

() = s"TextSon{${super.toString}, ${_level}}"




##### 4.2 实例化和使用

```scala
val obj: Text = new TextSon("TOP", "The Wild Roaring", "张培元", 86.32f)
4.3 类型判断和检查

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

val isIns: Boolean = obj.isInstanceOf[TextSon]

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

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1614278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle交换分区测试

1、用exchange分区表减少初始化过程中对业务中断的影响 2、创建分区表 create table t_p (id number,name varchar2(30),addr varchar2(50)) partition by range(id) (partition p1 values less than(10), partition p2 values less than(20), partition p3 values less …

冯唐成事心法笔记

文章目录 卷首语 管理是一生的日常,成事是一生的修行PART 1 知己 用好自己的天赋如何管理自我用好你的天赋成大事无捷径如何平衡工作和生活做一个真猛人做自己熟悉的行业掌控情绪如何对待妒忌和贪婪如何战胜自己,战胜逆境真正的高手都有破局思维有时候…

【支付宝】对接手机网站支付踩坑点记录

前言 简单记录一下对接Wap支付的问题,alipay和wxpay认证过程差不多,有个体商户或企业即可,前者文档不易懂后者还好,但是wxpay门槛高,个人认为pc网站支付(native支付)就是为了收300认证费! 应用公私钥 第一…

《剑指 Offer》专项突破版 - 面试题 112 : 最长递增路径(C++ 实现)

题目链接:最长递增路径 题目: 输入一个整数矩阵,请求最长递增路径的长度。矩阵中的路径沿着上、下、左、右 4 个方向前行。例如,下图中矩阵的最长递增路径的长度为 4,其中一条最长的递增路径为 3->4->5->8&…

护眼落地灯哪个牌子好?落地灯十大知名品牌

一款优异的落地灯不只有照明的作用,更有装修作用。只不过,市面上的落地灯产品很多,质量良莠不齐,很多人不知道怎么挑选是好。小编的主张是从品牌下手,挑选口碑上佳的品牌落地灯产品。若问护眼落地灯哪个牌子好&#xf…

Flask-SQLAlchemy 中使用显式主主数据库设置

1、问题背景 在一个 Flask-SQLAlchemy 项目中,用户想要使用显式主主数据库设置。具体而言,他想要能够从默认数据库中读取数据,并将数据持久化到两个主数据库中。他希望知道是否可以使用 Flask-SQLAlchemy 和 binds 来实现这一目标。 2、解决…

【MySQL篇】mysqlpump和mysqldump参数区别总汇(第三篇,总共四篇)

☘️博主介绍☘️: ✨又是一天没白过,我是奈斯,DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&am…

Windows 的常用命令(不分大小写)

Net user (查看当前系统所有的账户) net user yourname password /add 添加新用户 net localgroup administrators yourname /add 添加管理员权限 net user yourname /delete 删除用户 net user 命令 [colorred]说明:以下命令仅限持管理员…

[创业之路-106] :经济学十大陷阱与核心思想:系统论、社会进化论、周期论、阴阳互转论

目录 前言: 一、流动性陷阱。 二、中等收入陷阱。 三、修昔底德陷阱。 四、塔西佗陷阱。 五、金德尔伯格陷阱。 六、卢梭陷阱。 七、拉美陷阱。 八、阿喀琉斯之踵。 九、布拉德伯里悖论。 十、李约瑟之谜 结论:上述陷阱的…

负载均衡集群——Nginx

目录 1.Nginx反向代理实战 2.Nginx 反向代理和负载均衡实践 实验操作步骤 步骤 1 Nginx1 和 Nginx2 配置 步骤2 测试资源是否可用 步骤 3 安装和配置 Nginx 代理 步骤 4 代理服务器配置检测 步骤 5 在 Nginx1 和 Nginx2 配置虚拟主机 步骤 6 将虚拟主机添加入后端主机组…

Linux--基础IO(上)

目录 1. 文件的边角知识 1.1 文件是什么? 1.2 文件是怎么打开的? 1.3 进程与文件 进程与文件的关系 2. 重温c语言文件接口 2.1 打开文件的方式 2.2 读写文件接口的重温 2.2.1 写文件 2.2.2 读文件 3. 系统文件I/O 3.1 系统接口 3.2 系…

零信任网络安全技术雷达图3.0正式发布

伴随零信任理念的发展和实施,零信任技术体系的演进变革也日趋完善。易安联力图通过持续更新并优化零信任雷达图,以反映零信任技术在应对新型网络安全挑战中的创新和发展,为企业和组织提供前瞻性的技术建议,助力其构建更为强大和灵…

前端JS必用工具【js-tool-big-box】,日期时间相关工具二

上一节我们说到了工具中关于日期的详细转换,还有获取年月日时分秒的详细转换方法使用,同时可以灵活添加自己需要的单位,很便捷。这一节我们继续学习几个相关的方法 目录 1 安装和引入 2 某个时间距离现在的显示 3 获取某一年是是平年还是…

dataguard环境破坏后采用rman备份集重新部署

dataguard环境破坏后采用rman备份集重新部署 1. 环境 主库: 192.168.1.118 备库: 192.168.1.85 OS: Centos7 DB: 11.2.0.4 前提条件:dataguard之前已经搭建好,从库的spfile和密码文件不需要创建,主库的数据文件目录在从库必须存在,这里的场景是主库…

请编写一个函数void fun(int m,int k,int xx[]),该函数的功能是:将大于整数m且紧靠m的k个素数存入xx所指的数组中。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法和详细的解析。 题干 请编写一个函…

TVbox三端助手MAC+Windows+手机版带接口

Vbox这个目前大热的电视播放器,由于是空壳,于是接口成为非常核心的一环,很多网友制作的接口会进行加密,以防被人复制使用。 最近发现有人对此做了个专门解密的工具,解不解密的不重要的,分享迷倒是觉得这工…

树莓集团与企业协同育人,打造成都数字产业人才培养高地

树莓集团,作为成都数字产业的重要力量,深知企业协同育人的重要性。我们坚信,通过校企合作的模式,可以从供给侧结构性改革的角度出发,开展精准、高效的人才培养工作。我们既是企业,也是产业的代表&#xff0…

VUE识别图片文字OCR(tesseract.js)

效果:1&#xff1a; 效果图2&#xff1a; 一、安装tesseract.js npm i tesseract.js 二、静态页面实现 <template><div><div style"marginTop:100px"><input change"handleChage" type"file" id"image-input"…

uniapp使用腾讯地图实现商家定位

uniapp使用腾讯地图实现商家定位 一丶申请腾讯位置服务开发者密钥二丶下载微信小程序JavaScriptSDK三丶安全域名设置四、代码编写五、实现效果 一丶申请腾讯位置服务开发者密钥 官网教程&#xff1a;微信小程序JavaScript SDK | 腾讯位置服务 点击申请密钥 创建应用&#xf…

Hive 中常用的函数以及数据类型

数据类型 1.基本数据类型: 数据类型大小范围示例TINYINT1byte-128 ~ 127100YSMALLINT2byte-32768 ~ 32767100SINT4byte-2^32~ 2^32-1100BIGINT8byte-2^64~ 2^64-1100LFLOAT4byte单精度浮点数5.21DOUBLE8byte双精度浮点数5.21DECIMAL-高精度浮点数DECIMAL(9,8)BOOLEAN-布尔型tr…