目录
0.模式匹配
scala中有一个非常强大的模式匹配机制,可以应用在很多场景:
- switch语句
- 类型查询
- 使用模式匹配快速获取数据
1.简单模式匹配
在Java中,有switch关键字,可以简化if条件判断语句。在scala中,可以使用match表达式替代。
1.1 语法格式
变量 match {
case "常量1" => 表达式1
case "常量2" => 表达式2
case "常量3" => 表达式3
case _ => 表达式4 // 默认匹配
}
1.2 示例演示
需求说明
- 从控制台输入一个单词(使用StdIn.readLine方法)
- 判断该单词是否能够匹配以下单词,如果能匹配,返回一句话
- 打印这句话
参考代码
package com.robot.scalademo
import scala.io.StdIn
object _08ObjectDemo {
def main(args: Array[String]): Unit = {
while(true) { //while死循环,持续输入。
println("请输出一个词:")
// StdIn.readLine表示从控制台读取一行文本
val name = StdIn.readLine()
val result = name match {
case "hadoop" => "大数据分布式存储和计算框架"
case "zookeeper" => "大数据分布式协调服务框架"
case "spark" => "大数据分布式内存计算框架"
case _ => "未匹配"
}
println(result)
}
}
}
/**
请输出一个词:
hadoop
大数据分布式存储和计算框架
请输出一个词:
zookeeper
大数据分布式协调服务框架
请输出一个词:
spark
大数据分布式内存计算框架
请输出一个词:
Spark
未匹配
请输出一个词:
*
* */
2.匹配类型
除了像Java中的switch匹配数据之外,match表达式还可以进行类型匹配。如果我们要根据不同的数据类型,来执行不同的逻辑,也可以使用match表达式来实现。
2.1 语法格式
变量 match {
case 类型1变量名: 类型1 => 表达式1
case 类型2变量名: 类型2 => 表达式2
case 类型3变量名: 类型3 => 表达式3
...
case _ => 表达式4
}
2.2 示例演示
需求说明
- 定义一个变量为Any类型,然后分别给其赋值为"hadoop"、1、1.0
- 定义模式匹配,然后分别打印类型的名称
参考代码
package com.robot.scalademo
import scala.io.StdIn
object _08ObjectDemo {
def main(args: Array[String]): Unit = {
val a: Any = "hadoop" //注意这里a的类型是Any,这是其他所有类型的父类。
val result1 = a match {
case _: String => "String" //如果case表达式中无需使用到匹配到的变量,可以使用下划线代代替
case a1: Int => "Int"
case bb: Double => "Double"+bb
}
//val a: Any = "hadoop"
val b: Any = 1.5 //注意这里a的类型是Any,这是其他所有类型的父类。
val result2 = b match {
case _: String => "String"
case a1: Int => "Int"
case bb: Double => "Double"+bb //注意这里因为用到匹配的变量,所以不能用_来替换,否则报错。
}
println(result1) //String
println(result2) //Double1.5
}
}
尖叫提示:如果case表达式中无需使用到匹配到的变量,可以使用下划线_来代替,但是如果变量在后面的表达式中使用到了,则不能使用下划线代替,否则报错。
3.守卫的使用
在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]
- 否则,打印未匹配
参考代码
package com.robot.scalademo
import scala.io.StdIn
object _08ObjectDemo {
def main(args: Array[String]): Unit = {
println("请输入一个数字")
val a = StdIn.readInt()
val res1 = a match {
case s if a >= 0 && a <= 3 => println("[0-3]") //前面的变量可以任意命名
case _ if a >= 4 && a <= 8 => println("[3-8]")
case _ => println("未匹配")
}
}
}
/**
请输入一个数字
3
[0-3]
* */
4.匹配样例类
scala可以使用模式匹配来匹配样例类,从而可以快速获取样例类中的成员数据。后续,我们在开发Akka案例时,还会用到。
4.1示例演示
需求说明
- 创建两个样例类Customer、Order
- Customer包含姓名、年龄字段
- Order包含id字段
- 分别定义两个案例类的对象,并指定为Any类型
- 使用模式匹配这两个对象,并分别打印它们的成员变量值
参考代码
package com.robot.scalademo
object _08ObjectDemo {
// 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("未匹配")
}
}
}
/**
ID为:001
* */
5.匹配集合
scala中的模式匹配,还能用来匹配集合。可以匹配不同位置,不同个数的集合样式。
5.1 匹配集合中数组
示例说明
依次修改代码定义以下三个数组,使用匹配模式匹配。
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")
}
// 3 5
5.2 匹配元组
示例说明
依次修改代码定义以下两个元组,使用匹配模式匹配。
(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("未匹配")
}
//三个元素,5结尾的元组: 2 2 5
5.3 匹配列表
示例说明
依次修改代码定义以下列表,使用匹配模式匹配。
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("未匹配")
}
///0开头的列表
6. 变量声明中的模式匹配
在定义变量的时候,可以使用模式匹配快速获取数据
需求说明1
- 生成包含0-10数字的数组,使用模式匹配分别获取第二个、第三个、第四个元素
参考代码1
object _08ObjectDemo {
// 1. 创建两个样例类
case class Person(name:String, age:Int)
case class Order(id:String)
def main(args: Array[String]): Unit = {
val array = (1 to 10).toArray
val Array(_, x, y, z, _*) = array
println(x, y, z) // (2,3,4)
}
}
需求说明2
- 生成包含0-10数字的列表,使用模式匹配分别获取第一个、第二个元素
参考代码2
val list = (1 to 10).toList
val x :: y :: tail = list
println(x, y) //(1,2)