学习链接:https://www.bilibili.com/video/BV1Xh411S7bP?p=125&spm_id_from=pageDriver


1 基本语法

所有case都不匹配,执行case 分支,类似default。没有case 分支,抛出MatchError
每个case中,不需要使用break语句,自动中断case
match case语句可以匹配任何类型
=> 后面的代码块,直到下一个 case 语句之前的代码是作为一个整体执行,可以
使用{}括起来,也可以不括

  1. object Test01_PatterMatchBase {
  2. def main(args: Array[String]): Unit = {
  3. // 1. 基本定义语法
  4. val x: Int = 2
  5. val y: String = x match {
  6. case 1 => "one"
  7. case 2 => "two"
  8. case 3 => "three"
  9. case _ => "other" // case _ 相当于default,若没有case _分支,都不匹配,MatchError
  10. }
  11. println(y)
  12. // 2. 示例:用模式匹配实现简单二元运算
  13. val a = 25
  14. val b = 13
  15. def matchDualOp(op: Char) = op match {
  16. case '+' => a + b
  17. case '-' => a - b
  18. case '*' => a * b
  19. case '/' => a / b
  20. case '%' => a % b
  21. case _ => "非法运算符"
  22. }
  23. println(matchDualOp('+'))
  24. }
  25. }

2 模式守卫

如果想要表达匹配某个范围的数据,需要在模式匹配中增加条件守卫

// 模式守卫
// 求一个整数的绝对值
def abs(num: Int): Int = {
  num match {
    case i if i >= 0 => i
    case i if i < 0 => -i
  }
}

println(abs(67)) // 67
println(abs(0)) // 0
println(-24) // -24

3 模式匹配类型

3.1 匹配常量

object Test02_MatchTypes {
  def main(args: Array[String]): Unit = {
    // 1. 匹配常量
    def describeConst(x: Any): String = x match {
      case 1 => "Num one"
      case "hello" => "String hello"
      case true => "Boolean true"
      case '+' => "Char +"
      case _ => ""
    }

    println(describeConst("hello"))
  }
}

3.2 匹配类型

// 2. 匹配类型
def describeType(x: Any): String = x match {
  case i: Int => "Int " + i
  case s: String => "String " + s
  case list: List[String] => "List " + list
  case array: Array[Int] => "Array[Int] " + array.mkString(",")
  case a => "Something else:" + a
}

println(describeType(List(2, 3))) // 泛型擦除
println(describeType(Array(2, 3))) // 没有泛型擦除
println(describeType(Array("aaa", "vvv"))) // Something else:[Ljava.lang.String;@6bdf28bb

3.3 匹配数组

// 3. 匹配数组
for (arr <- List(
  Array(0),
  Array(1),
  Array(0, 1, 0),
  Array(1, 1, 0),
  Array(2, 3, 7, 15),
  Array("hello", 20, 30)
)) {
  val result = arr match {
    case Array(0) => "0"
    case Array(1, 0) => "Array(1, 0)"
    case Array(x, y) => "Array: " + x + ", " + y // 匹配两元素数组
    case Array(0, _*) => "以0开头的数组"
    case Array(x, 1, z) => "中间为1的3元素数组"
    case _ => "something else"
  }
  println(result)

3.4 匹配列表

// 4. 匹配列表
// 方式一
for (list <- List(
  List(0),
  List(1, 0),
  List(0, 0, 0),
  List(1, 1, 0),
  List(88)
)) {
  val result = list match {
    case List(0) => "0"
    case List(x, y) => "List(x, y): " + x + ", " + y
    case List(0, _*) => "List(0, ...)"
    case List(a) => "List(a): " + a
    case _ => "something else"
  }
  println(result)
  /*
  0
  List(x, y): 1, 0
  List(0, ...)
  something else
  List(a): 88
  */
}
// 方式二
val list = List(1, 2, 5, 7, 24)
list match {
  case first :: second :: rest => println(s"first: $first, second: $second, rest: $rest")
  case _ => println("something else")
}
// first: 1, second: 2, rest: List(5, 7, 24)

3.5 匹配元组

// 5. 匹配元组
for (tuple <- List(
  (0, 1),
  (0, 0),
  (0, 1, 0),
  (0, 1, 1),
  (1, 23, 56),
  ("hello", true, 0.5)
)) {
  val result = tuple match {
    case (a, b) => "" + a + ", " + "b"
    case (0, _) => "(0, _) "
    case (a, 1, _) => "(a, 1, _) " + a
    case (x, y, z) => "(x, y, z) " + x + " " + y + " " + z
    case _ => "something else"
  }
  println(result)
}

3.6 匹配对象及样例类

object Test04_MatchObject {
  def main(args: Array[String]): Unit = {
    val student = new Student("aaa", 28)

    // 针对对象实例的内容进行匹配
    val result = student match {
      case Student("aaa", 28) => "aaa, 28"
      case _ => "else"
    }

    println(result) // aaa, 28
  }
}

// 定义类
class Student(val name: String, val age: Int)

// 定义伴生对象
object Student {
  def apply(name: String, age: Int): Student = new Student(name, age)

  // 必须实现一个unapply方法,用来对对象属性进行拆解
  def unapply(student: Student): Option[(String, Int)] = {
    if(student == null) {
      None
    } else {
      Some((student.name, student.age))
    }
  }
}

样例类:

object Test05_MatchCaseClass {
  def main(args: Array[String]): Unit = {
    val student = new Student1("aaa", 18)

    // 针对对象实例的内容进行匹配
    val result = student match {
      case Student1("aaa", 28) => "aaa, 28"
      case _ => "else"
    }

    println(result) // else
  }
}

// 定义样例类
case class Student1(name: String, age: Int)

4 偏函数中的模式匹配

偏函数定义

val second: PartialFunction[List[Int], Option[Int]] = {
  case x :: y :: _ => Some(y)
}
object Test06_PartialFunction {
  def main(args: Array[String]): Unit = {
    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 13))

    // 1. map转换,实现key不变,value 2倍
    val newList = list.map(tuple => (tuple._1, tuple._2 * 2))

    // 2. 用模式匹配对元组元素赋值,实现功能
    val newList2 = list.map(
      tuple => {
        tuple match {
          case (word, count) => (word, count * 2)
        }
      }
    )

    // 3. 省略lambda表达式的写法,进行简化
    val newList3 = list.map {
      case (word, count) => (word, count * 2)
    }
    println(newList) // List((a,24), (b,70), (c,54), (a,26))
    println(newList2) // List((a,24), (b,70), (c,54), (a,26))
    println(newList3) // List((a,24), (b,70), (c,54), (a,26))

    // 偏函数的应用,求绝对值
    // 对输入数据分为不同的情形:正、负、0
    val positionAbs: PartialFunction[Int, Int] = {
      case x if x > 0 => x
    }
    val negativeAbs: PartialFunction[Int, Int] = {
      case x if x < 0 => -x
    }
    val zeroAbs: PartialFunction[Int, Int] = {
      case 0 => 0
    }

    def abs(x: Int): Int = (positionAbs orElse negativeAbs orElse zeroAbs)(x)

    println(abs(-67))
    println(abs(35))
    println(0)
  }
}