模式匹配-基础使用1

51 阅读5分钟

一、问题分析与解决:从 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 caseJava switch-case
语法性质表达式式(可直接返回值)语句式(需手动 break,否则穿透)
匹配类型支持任意类型(字符串、数字、对象等)仅支持基本类型 / 字符串(Java7+)
默认匹配case _default
代码简洁性无嵌套,一行匹配 + 返回嵌套繁琐,需手动添加 break

标准格式

// 待匹配值 match { 匹配模式 => 结果/逻辑 }
待匹配值 match {
  case 模式1 => 匹配成功后的结果1/执行逻辑1
  case 模式2 => 匹配成功后的结果2/执行逻辑2
  // ... 更多匹配模式
  case _ => 所有模式不匹配时的默认结果/逻辑(建议必加)
}

2. 执行流程

  1. 从第一个case开始,依次比对 “待匹配值” 与 “匹配模式”;
  2. 一旦匹配成功,执行该case后的逻辑 / 返回值,自动终止匹配(无需 Java 的 break);
  3. 若所有case均不匹配,执行case _(通配符)对应的逻辑;
  4. 若未定义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. 场景 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")
  }
}