scala_样例类、样例对象、模式匹配

本文介绍了Scala中的样例类,包括定义、可变成员变量、apply、toString、equals、hashCode、copy方法。接着讨论了样例对象的定义及其在枚举和消息传递中的应用。此外,还详细讲解了模式匹配,包括简单模式匹配、类型查询、守卫以及匹配集合(如数组、列表和元组)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

样例类

样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类),在后续要学习并发编程和spark、flink这些框架也都会经常使用它。



定义样例类

语法格式

case class 样例类名([var/val] 成员变量名1:类型1, 成员变量名2:类型2, 成员变量名3:类型3)
  • 如果要实现某个成员变量可以被修改,可以添加var
  • 默认为val,可以省略


示例 | 定义一个样例类

需求

  • 定义一个Person样例类,包含姓名和年龄成员变量
  • 创建样例类的对象实例(“张三”、20),并打印它

参考代码

object _01CaseClassDemo {
  case class Person(name:String, age:Int)

  def main(args: Array[String]): Unit = {
    val zhangsan = Person("张三", 20)

    println(zhangsan)
  }
}


示例 | 可变成员变量

需求

  • 定义一个Person样例类,包含姓名和年龄成员变量
  • 创建样例类的对象实例(“张三”、20)
  • 修改张三的年龄为23岁,并打印

参考代码

object _02CaseClassDemo {
  case class Person(var name:String, var age:Int)

  def main(args: Array[String]): Unit = {
    val zhangsan = Person("张三", 20)

    zhangsan.age = 23

    println(zhangsan)
  }
}


# 样例类的方法

当我们定义一个样例类,编译器自动帮助我们实现了以下几个有用的方法:

  • apply方法
  • toString方法
  • equals方法
  • hashCode方法
  • copy方法


apply方法

apply方法可以让我们快速地使用类名来创建对象。参考以下代码:

case class CasePerson(name:String, age:Int)

object CaseClassDemo {
  def main(args: Array[String]): Unit = {
    val lisi = CasePerson("李四", 21)
    println(lisi.toString)
  }
}


toString方法

toString返回样例类名称(成员变量1, 成员变量2, 成员变量3…),我们可以更方面查看样例类的成员

case class CasePerson(name:String, age:Int)

object CaseClassDemo {
  def main(args: Array[String]): Unit = {
    val lisi = CasePerson("李四", 21)
    println(lisi.toString)
    // 输出:CasePerson(李四,21)
  }
}


equals方法

样例类自动实现了equals方法,可以直接使用==比较两个样例类是否相等,即所有的成员变量是否相等


示例

  • 创建一个样例类Person,包含姓名、年龄
  • 创建名字年龄分别为"李四", 21的两个对象
  • 比较它们是否相等
val lisi1 = CasePerson("李四", 21)
val lisi2 = CasePerson("李四", 21)
println(lisi1 == lisi2)
// 输出:true


hashCode方法

样例类自动实现了hashCode方法,如果所有成员变量的值相同,则hash值相同,只要有一个不一样,则hash值不一样。


示例

  • 创建名字年龄分别为"李四", 21的对象
  • 再创建一个名字年龄分别为"李四", 22的对象
  • 分别打印这两个对象的哈希值
val lisi1 = CasePerson("李四", 21)
val lisi2 = CasePerson("李四", 22)

println(lisi1.hashCode())
println(lisi2.hashCode())


copy方法

样例类实现了copy方法,可以快速创建一个相同的实例对象,可以使用带名参数指定给成员进行重新赋值


示例

  • 创建名字年龄分别为"李四", 21的对象
  • 通过copy拷贝,名字为"王五"的对象
val lisi1 = CasePerson("李四", 21)

val wangwu = lisi1.copy(name="王五")
println(wangwu)


样例对象

它主要用在两个地方:

  1. 定义枚举
  2. 作为没有任何参数的消息传递(后面Akka编程会讲到)


定义

使用case object可以创建样例对象。样例对象是单例的,而且它没有主构造器

语法格式

case object 样例对象名


示例 | 定义枚举

需求说明

  • 定义一个性别Sex枚举,它只有两个实例(男性——Male、女性——Female)
  • 创建一个Person类,它有两个成员(姓名、性别)
  • 创建两个Person对象(“张三”、男性)、(“李四”、“女”)

参考代码

trait Sex /*定义一个性别特质*/
case object Male extends Sex		// 定义一个样例对象并实现了Sex特质
case object Female extends Sex		

case class Person(name:String, sex:Sex)

object CaseClassDemo {
  def main(args: Array[String]): Unit = {
    val zhangsan = Person("张三", Male)

    println(zhangsan)
  }
}


# 模式匹配

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

  • switch语句
  • 类型查询
  • 使用模式匹配快速获取数据


简单模式匹配

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


语法格式

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


示例

需求说明

  1. 从控制台输入一个单词(使用StdIn.readLine方法)
  2. 判断该单词是否能够匹配以下单词,如果能匹配,返回一句话
  3. 打印这句话
单词返回
hadoop大数据分布式存储和计算框架
zookeeper大数据分布式协调服务框架
spark大数据分布式内存计算框架
未匹配未匹配

参考代码

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

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

println(result)


# 匹配类型

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



定义

语法格式

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


示例

需求说明

  • 定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0
  • 定义模式匹配,然后分别打印类型的名称

参考代码

val a:Any = "hadoop"

val result = a match {
    case _:String => "String"
    case _:Int => "Int"
    case _:Double => "Double"
}

println(result)


[!NOTE]

如果case表达式中无需使用到匹配到的变量,可以使用下划线代代替

守卫

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

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条件判断



示例

需求说明

  • 从控制台读入一个数字a(使用StdIn.readInt)
  • 如果 a >= 0 而且 a <= 3,打印[0-3]
  • 如果 a >= 4 而且 a <= 8,打印[3,8]
  • 否则,打印未匹配

参考代码

val a = StdIn.readInt()

a match {
    case _ if a >= 0 && a <= 3 => println("[0-3]")
    case _ if a >= 4 && a <= 8 => println("[3-8]")
    case _ => println("未匹配")
}


# 匹配样例类

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



示例

需求说明

  • 创建两个样例类Customer、Order
    • Customer包含姓名、年龄字段
    • Order包含id字段
  • 分别定义两个案例类的对象,并指定为Any类型
  • 使用模式匹配这两个对象,并分别打印它们的成员变量值

参考代码

// 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"ID为:${id1}")
        case _ => println("未匹配")
    }
}

匹配集合

scala中的模式匹配,还能用来匹配集合。



匹配数组

示例说明

  • 依次修改代码定义以下三个数组

    Array(1,x,y)   // 以1开头,后续的两个元素不固定
    Array(0)	   // 只匹配一个0元素的元素
    Array(0, ...)  // 可以任意数量,但是以0开头
    
  • 使用模式匹配上述数组

参考代码

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")
}


匹配列表

示例说明

  • 依次修改代码定义以下三个列表

    List(0)				// 只保存0一个元素的列表
    List(0,...)   		// 以0开头的列表,数量不固定
    List(x,y)	   		// 只包含两个元素的列表  
    
  • 使用模式匹配上述列表

参考代码

val list = List(0, 1, 2)

list 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的元组
    
  • 使用模式匹配上述元素

参考代码

val tuple = (2, 2, 5)

tuple match {
    case (1, x, y) => println(s"三个元素,1开头的元组:1, ${x}, ${y}")
    case (x, y, 5) => println(s"三个元素,5结尾的元组:${x}, ${y}, 5")
    case _ => println("未匹配")
}


# 变量声明中的模式匹配

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



示例 | 获取数组中的元素

需求说明

  • 生成包含0-10数字的数组,使用模式匹配分别获取第二个、第三个、第四个元素

参考代码

val array = (1 to 10).toArray
val Array(_, x, y, z, _*) = array

println(x, y, z)


示例 | 获取List中的数据

需求说明

  • 生成包含0-10数字的列表,使用模式匹配分别获取第一个、第二个元素

参考代码

val list = (1 to 10).toList
val x :: y :: tail = list

println(x, y)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值