模式匹配-基础使用2

39 阅读3分钟

五、高阶匹配(三):数组元素特征匹配

核心特性

可根据数组的元素个数、首元素值、元素特征进行灵活匹配,支持通配符_*表示任意多个后续元素。

1. 常用匹配模式

匹配模式含义
Array(0)匹配长度为 1,且元素为 0 的数组
Array(1, x, y)匹配长度为 3,且首元素为 1 的数组
Array(0, _*)匹配首元素为 0,长度任意的数组
Array(_*)匹配任意数组(等同于 case _)

2. 演示代码

/**
 * 高阶匹配:数组元素特征匹配
 */
object ArrayFeatureMatchDemo {
  def main(args: Array[String]): Unit = {
    // 定义不同特征的数组
    val arr1 = Array(0)                // 长度1,元素0
    val arr2 = Array(1, 2, 3)           // 长度3,首元素1
    val arr3 = Array(0, 2, 8, 10, 11)   // 首元素0,长度5
    val arr4 = Array(1, 2, 8, 10, 11)   // 首元素1,长度5

    // 测试每个数组的匹配结果
    testArrayMatch(arr1)
    testArrayMatch(arr2)
    testArrayMatch(arr3)
    testArrayMatch(arr4)
  }

  /**
   * 数组特征匹配逻辑
   * @param arr 待匹配的数组
   */
  def testArrayMatch(arr: Array[Int]): Unit = {
    arr match {
      case Array(1, x, y) => println(s"数组 $arr:匹配到长度为3,且第一个元素为1")
      case Array(0) => println(s"数组 $arr:匹配到长度为1,且只有一个元素0")
      case Array(0, _*) => println(s"数组 $arr:匹配到长度为n,第一个元素为0")
      case _ => println(s"数组 $arr:其他情况")
    }
  }
}

六、高阶匹配(四):案例类(样例类)匹配

核心特性

可根据样例类的类型字段值进行精准匹配,自动解析样例类的字段,常用于面向对象场景的模式匹配。

演示代码

/**
 * 高阶匹配:案例类(样例类)匹配
 * 功能:匹配不同几何图形,计算对应面积
 */
object CaseClassMatchDemo {
  // 定义样例类(圆、矩形)
  case class Circle(radius: Double)
  case class Rectangle(width: Double, height: Double)

  def main(args: Array[String]): Unit = {
    // 创建样例类对象
    val circle = Circle(3.0)
    val rectangle = Rectangle(4.0, 5.0)
    val unknown = "非几何图形"

    // 计算并打印面积
    println(s"圆的面积:${calculateArea(circle)}")
    println(s"矩形的面积:${calculateArea(rectangle)}")
    println(s"未知对象的面积:${calculateArea(unknown)}")
  }

  /**
   * 匹配样例类,计算面积
   * @param shape 任意类型的几何图形/对象
   * @return 图形面积(非图形返回0.0)
   */
  def calculateArea(shape: Any): Double = shape match {
    case Circle(r) => Math.PI * r * r // 匹配Circle类,解析半径r
    case Rectangle(w, h) => w * h     // 匹配Rectangle类,解析宽w、高h
    case _ => 0.0                     // 非图形对象返回0.0
  }
}

七、变量声明中的模式匹配

核心特性

在变量声明时直接使用模式匹配,快速提取数组 / 元组的指定元素,简化代码。

1. 基础实现(无模式匹配)

/**
 * 变量声明:基础实现(提取数组前3个元素)
 */
object VarDeclareBasic {
  def main(args: Array[String]): Unit = {
    val arr = Array(1, 2, 3, 4, 5)
    // 手动通过索引提取元素
    val x = arr(0)
    val y = arr(1)
    val z = arr(2)
    println(s"x=$x, y=$y, z=$z") // 输出:x=1, y=2, z=3
  }
}

2. 模式匹配实现(简化版)

/**
 * 变量声明:模式匹配实现(快速提取数组元素)
 */
object VarDeclareWithMatch {
  def main(args: Array[String]): Unit = {
    val arr = Array(1, 2, 3, 4)
    // 模式匹配提取前3个元素,_* 忽略后续所有元素
    val Array(x, y, z, _*) = arr
    println(s"x=$x, y=$y, z=$z") // 输出:x=1, y=2, z=3

    // 元组变量声明的模式匹配
    val tuple = (10, "Scala", true)
    val (a, b, c) = tuple // 提取元组所有元素
    println(s"a=$a, b=$b, c=$c") // 输出:a=10, b=Scala, c=true
  }
}

八、守卫语句(带条件的模式匹配)

1. 基本格式

待匹配值 match {
  case 模式 if 守卫条件 => 结果/逻辑 // 守卫条件为布尔表达式
  // 其他case分支
  case _ => 默认结果/逻辑
}

2. 基础案例:数字区间匹配(控制台输入)

import scala.io.StdIn

/**
 * 守卫语句:数字区间匹配(控制台交互)
 */
object GuardMatchBasic {
  def main(args: Array[String]): Unit = {
    // 从控制台读取数字
    println("请输入一个整数:")
    val a = StdIn.readInt()

    // 带守卫的模式匹配
    a match {
      case x if x >= 0 && x <= 3 => println(s"$x 属于区间 [0-3]")
      case x if x >= 4 && x <= 8 => println(s"$x 属于区间 [4-8]")
      case _ => println(s"$x 未匹配任何区间")
    }
  }
}

3. 进阶案例:1-100 数字特征匹配

/**
 * 守卫语句:1-100数字特征匹配
 * 功能:匹配大于10的偶数、大于80的奇数
 */
object GuardMatchAdvanced {
  def main(args: Array[String]): Unit = {
    // 遍历1-100,使用带守卫的模式匹配
    for (i <- 1 to 100) {
      i match {
        case x if x > 10 && x % 2 == 0 => println(s"$i 是大于10的偶数")
        case x if x > 80 && x % 2 != 0 => println(s"$i 是大于80的奇数")
        case _ => // 忽略其他数字,不输出
      }
    }
  }
}

九、for 表达式中的模式匹配

场景需求

从 Map 中筛选出出生年份为 1971 的创业者信息,提供两种实现方式。

1. 方式 1:for + if 守卫(基础版)

/**
 * for表达式:if守卫筛选Map数据
 */
object ForMatchWithGuard {
  def main(args: Array[String]): Unit = {
    val m1 = Map(
      "马云 - 阿里巴巴" -> 1964,   "马化腾 - 腾讯" -> 1971,
      "李彦宏 - 百度" -> 1968,   "雷军 - 小米" -> 1969,
      "丁磊 - 网易" -> 1971,     "张一鸣 - 字节跳动" -> 1983,
      "刘强东 - 京东" -> 1974,   "程维 - 滴滴" -> 1983,
      "王兴 - 美团" -> 1979,     "周鸿祎 - 360" -> 1970,
      "黄峥 - 拼多多" -> 1980,   "李想 - 理想汽车" -> 1981,
      "何小鹏 - 小鹏汽车" -> 1977, "贾跃亭 - 乐视" -> 1973,
      "陈天桥 - 盛大网络" -> 1973, "周源 - 知乎" -> 1980,
      "王小川 - 搜狗" -> 1978
    )

    // for + if守卫:筛选年份=1971的记录
    println("出生年份为1971的创业者(if守卫版):")
    for ((key, year) <- m1 if year == 1971) {
      println(s"$key -> $year")
    }
  }
}

2. 方式 2:for + 模式匹配(优化版)

/**
 * for表达式:模式匹配筛选Map数据
 */
object ForMatchWithPattern {
  def main(args: Array[String]): Unit = {
    val m1 = Map(
      "马云 - 阿里巴巴" -> 1964,   "马化腾 - 腾讯" -> 1971,
      "李彦宏 - 百度" -> 1968,   "雷军 - 小米" -> 1969,
      "丁磊 - 网易" -> 1971,     "张一鸣 - 字节跳动" -> 1983,
      "刘强东 - 京东" -> 1974,   "程维 - 滴滴" -> 1983,
      "王兴 - 美团" -> 1979,     "周鸿祎 - 360" -> 1970,
      "黄峥 - 拼多多" -> 1980,   "李想 - 理想汽车" -> 1981,
      "何小鹏 - 小鹏汽车" -> 1977, "贾跃亭 - 乐视" -> 1973,
      "陈天桥 - 盛大网络" -> 1973, "周源 - 知乎" -> 1980,
      "王小川 - 搜狗" -> 1978
    )

    // for + 模式匹配:直接匹配年份=1971的记录
    println("出生年份为1971的创业者(模式匹配版):")
    for ((key, 1971) <- m1) {
      println(s"$key -> 1971")
    }
  }
}

十、运行说明(可直接复制到在线 Scala 环境)

1. 推荐在线运行环境

2. 运行步骤

  1. 复制任意模块的代码(如ProvinceCodeLookupByMatch);
  2. 粘贴到在线 Scala 编辑区,点击 “运行” 按钮;
  3. 可自由修改测试用例(如编码、数字、数组等),验证不同场景。

3. 核心知识点总结

  1. match case是 Scala 替代 Java switch-case 的核心语法,支持表达式式返回值;
  2. 基础特性:值匹配、自动终止、case _默认匹配;
  3. 高阶特性:元组长度匹配、类型匹配、数组特征匹配、样例类匹配;
  4. 扩展特性:变量声明匹配、守卫语句(带条件匹配)、for 表达式匹配;
  5. 最佳实践:始终添加case _,避免MatchError;合理使用守卫语句提升匹配灵活性。