一、问题分析与解决:从 if-else 到模式匹配
场景需求
根据省份编码匹配对应省份名称,先通过if-else实现基础逻辑,再用 Scalamatch case优化,对比两种实现方式的差异。
1. if-else 实现省份编码查询
* 用if-else实现省份编码查询
* 功能:输入省份编码,返回对应省份名称
*/
object ProvinceCodeLookup {
def main(args: Array[String]): Unit = {
// 测试编码,可自由替换(如"33"、"11"、"99")
val code = "42"
// 调用方法获取省份名称
val provinceName = getProvinceName(code)
// 打印结果
println(s"省份编码 $code 对应的省份:$provinceName")
}
/**
* 编码转省份名称(if-else版)
* @param code 省份编码(字符串类型)
* @return 省份名称/未匹配提示
*/
def getProvinceName(code: String): String = {
if (code == "42") {
"湖北"
} else if (code == "33") {
"浙江"
} else if (code == "11") {
"北京"
} else if (code == "31") {
"上海"
} else {
"未找到对应的省份"
}
}
}
2. match case 重构(替代 Java switch-case)
代码如下:
/**
* 用match case实现省份编码查询(优化版)
* 优势:无需嵌套,代码更简洁,自动终止匹配(无需break)
*/
object ProvinceCodeLookupByMatch {
def main(args: Array[String]): Unit = {
// 多组测试用例
val testCodes = List("42", "33", "11", "31", "99")
testCodes.foreach { code =>
val provinceName = getProvinceName(code)
println(s"省份编码 $code 对应的省份:$provinceName")
}
}
/**
* 编码转省份名称(match case版)
* @param code 省份编码
* @return 省份名称/未匹配提示
*/
def getProvinceName(code: String): String = code match {
case "42" => "湖北"
case "33" => "浙江"
case "11" => "北京"
case "31" => "上海"
case _ => "未找到对应的省份" // 通配符,匹配所有未命中情况
}
}
二、match case 基本格式与核心特性
1. 基本格式(对比 Java switch-case)
| 特性 | Scala match case | Java switch-case |
|---|---|---|
| 语法性质 | 表达式式(可直接返回值) | 语句式(需手动 break,否则穿透) |
| 匹配类型 | 支持任意类型(字符串、数字、对象等) | 仅支持基本类型 / 字符串(Java7+) |
| 默认匹配 | case _ | default |
| 代码简洁性 | 无嵌套,一行匹配 + 返回 | 嵌套繁琐,需手动添加 break |
标准格式:
// 待匹配值 match { 匹配模式 => 结果/逻辑 }
待匹配值 match {
case 模式1 => 匹配成功后的结果1/执行逻辑1
case 模式2 => 匹配成功后的结果2/执行逻辑2
// ... 更多匹配模式
case _ => 所有模式不匹配时的默认结果/逻辑(建议必加)
}
2. 执行流程
- 从第一个
case开始,依次比对 “待匹配值” 与 “匹配模式”; - 一旦匹配成功,执行该
case后的逻辑 / 返回值,自动终止匹配(无需 Java 的 break); - 若所有
case均不匹配,执行case _(通配符)对应的逻辑; - 若未定义
case _且无匹配项,会抛出MatchError异常。
3. 基础示例:数字转英文单词
/**
* 基础示例:数字(1-5)转对应英文单词
*/
object NumberToEnglishDemo {
def main(args: Array[String]): Unit = {
val num = 5
// 模式匹配获取英文单词
val result = num match {
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
case 4 => "Four"
case 5 => "Five"
case _ => "Other" // 非1-5的数字均匹配此分支
}
println(s"数字 $num 对应的英文:$result")
}
}
4. 学生练习:特殊场景验证
- 场景 1:case _ 放在前面结果:
case _会匹配所有值,后续case分支永远不会执行(相当于 Java switch 把 default 放在最前面)。示例代码:
object MatchSpecialCase1 {
def main(args: Array[String]): Unit = {
val num = 3
val result = num match {
case _ => "Other" // 放在前面,优先匹配
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
}
println(result) // 输出:Other
}
}
场景 2:省略 case _ 且无匹配项结果:程序抛出MatchError异常,导致程序崩溃。示例代码:
object MatchSpecialCase2 {
def main(args: Array[String]): Unit = {
val num = 6
val result = num match {
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
case 4 => "Four"
case 5 => "Five"
// 省略case _
}
println(result) // 抛出:scala.MatchError
}
}
三、高阶匹配(一):元组元素数量匹配
核心特性
Scala 模式匹配支持根据元组元素个数进行匹配,无需精准匹配元组的值,仅匹配元组长度。
演示代码
/**
* 高阶匹配:元组元素数量匹配
*/
object TupleLengthMatchDemo {
def main(args: Array[String]): Unit = {
// 定义不同长度的元组
val t2 = (2, 3) // 2个元素
val t3 = (2, 3, 4) // 3个元素
val t4 = (2, 3, 4, 5) // 4个元素
// 打印不同元组的匹配结果
println(s"元组 $t2 匹配结果:${matchTupleLength(t2)}")
println(s"元组 $t3 匹配结果:${matchTupleLength(t3)}")
println(s"元组 $t4 匹配结果:${matchTupleLength(t4)}")
}
/**
* 根据元组元素个数匹配
* @param value 任意类型的元组
* @return 元组长度描述
*/
def matchTupleLength(value: Any): String = value match {
case (first, second) => "有两个元素" // 匹配2元素元组
case (x1, x2, x3) => "有三个元素" // 匹配3元素元组
case _ => "其他情况" // 匹配其他长度元组
}
}
四、高阶匹配(二):变量类型匹配
核心特性
支持根据变量的数据类型进行匹配,无需关心变量的值,仅匹配类型,是 Scala 特有的强大功能。
1. 基本格式
对象名 match {
case 变量名1: 类型1 => 表达式1
case 变量名2: 类型2 => 表达式2
case 变量名3: 类型3 => 表达式3
// 其他case分支
case _ => 默认表达式
}
// 若变量名未被使用,可用_替代:case _: Int => 表达式
2. 演示代码
**
* 高阶匹配:变量类型匹配
*/
object TypeMatchDemo {
def main(args: Array[String]): Unit = {
// 定义不同类型的变量(Any类型可接收任意值)
val testValues = List(100, 3.14, "Scala", true, List(1,2,3))
// 遍历测试所有类型
testValues.foreach { value =>
processValue(value)
}
}
/**
* 匹配变量类型并打印描述
* @param value 任意类型的值
*/
def processValue(value: Any): Unit = value match {
case i: Int => println(s"这是一个整数:$i")
case d: Double => println(s"这是一个双精度浮点数:$d")
case s: String => println(s"这是一个字符串:$s")
case b: Boolean => println(s"这是一个布尔值:$b")
case _: List[_] => println(s"这是一个列表:$value")
case _ => println(s"这是其他类型:$value")
}
}