企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # 简介 与default等效的捕获所有的`case _` 模式.如果没有模式匹配,抛出MatchError,每个case中,不用break语句.可以在match中使用任何类型,而不仅仅是数字 # 完全匹配 ~~~ object CaseDemo extends App { val arr = Array("111", "222", "333") val name = arr(Random.nextInt(arr.length)) println(name) name match { case "111" => println("111") case "222" => println("222") case _ => println("nnnnnnnn") } } ~~~ # 类型匹配 ~~~ object CaseDemo2 extends App { val arr = Array("hello", 1, -2.0, CaseDemo2) val elem = arr(2) println(elem) elem match { case x: Int => println("Int " + x) case y: Double if(y>=0) => println("Double " + y) case z: String => println("String " + z) case CaseDemo2 => { println("case demo 2") } case _ => { println("default") } } # 打印类型 println(elem.getClass.getName) } ~~~ 提示: Map类型的泛型在匹配的时候,会自动删除泛型类型,只会匹配到Map类型,而不会精确到Map里面的泛型类型 ~~~ var obj = Map("a" -> 1) obj match { case m1: Map[String, String] => println("这是Map[String, String]") case m2: Map[String, Int] => println("这是Map[String, Int]") } println(obj + " : " + obj.getClass.getName) ~~~ # 数组匹配 ~~~ object CaseDemo3 extends App { val arr = Array(0, 1, 7, 0) arr match { case Array(1, 5, x, y) => println(x + " " + y) case Array(1, 1, x, y) => println("only 0") # 匹配数组从0开始 case Array(0, _*) => println("0...") case _ => println("something else") } } ~~~ # 链表匹配 ~~~ object CaseDemo4 extends App { val lst = List(0, 1) lst match { //Nil代表空列表 List(0) case 0 :: Nil => println("only 0") //s方式拼接字符串 case x :: y :: Nil => println(s"x $x y $y") case 0 :: a => println(s"0 ... $a") case _ => println("something else") } } ~~~ # 元组匹配 ~~~ object CaseDemo5 extends App { val tup = (6, 3, 5) tup match { case (1, x, y) => println(s"hello 123 $x, $y") case (_, z, 5) => println(z) case _ => println("else") } } ~~~ # 类匹配 ~~~ //可以模式匹配 case class SubmitTask(id: String, name: String) case class HeartBeat(time: Long) case object CheckTimeOutTask object CaseDemo4 extends App { val arr = Array(CheckTimeOutTask, HeartBeat(123), HeartBeat(88888), new HeartBeat(88888), SubmitTask("0001", "task-0001")) val a = arr(Random.nextInt(arr.length)) println(a) a match { case SubmitTask(id, name) => { println(s"$id, $name") } case HeartBeat(time) => { println(time) } case CheckTimeOutTask => { println("check") } } } ~~~ # 偏函数 被包在花括号内没有match一组case语句是一个偏函数,它是`PartialFunction[A,B]`的一个实例,A代表参数类型,B代表返回实例,常用输入模式匹配 ~~~ object PartialFuncDemo { //偏函数 def func1: PartialFunction[String, Int] = { case "one" => 1 case "two" => 2 case _ => -1 } //其他方式实现 def func2(num: String): Int = num match { case "one" => 1 case "two" => 2 case _ => -1 } def main(args: Array[String]): Unit = { println(func1("one")) println(func2("one")) } } ~~~ 匿名偏函数 ~~~ object CaseDemo1 extends App { // val result = List(1, 2, 3, "heihei", 5).map{case i: Int => i * 2} val result2 = List(1, 2, 3, "heihei", 5).collect{case i: Int => i * 2} println(result2) } ~~~ map不能用,因为map不会检查每个元素是不是能应用到这个函数上 函数上有类型约束的,map不检查 collect会检查 输出 ~~~ List(2, 4, 6, 10) ~~~ 实现策略 ~~~ object CaseDemo1 extends App { val f1 = new PartialFunction[Any, Int] { //把类型转为Int,并加1 def apply(any: Any) = any.asInstanceOf[Int] + 1 //检查类型 def isDefinedAt(any: Any) = if (any.isInstanceOf[Int]) true else false } //collect会调用isDefinedAt,map不会 val result = List(1, 3, 5, "seven") collect f1 println(result) } ~~~ # 守卫 像if表达式一样,match也提供守卫功能,守卫可以是任何boolean条件 ~~~ val ch = 3 var sign = 0 ch match { case '+' => sign = '+' case '-' => sign = '-' case _ if ch.toString.equals("3") => sign = 3 case _ => sign = -1 } println(sign) ~~~ # 模式中的变量 如果在case关键字后面跟变量名,那么match前表达式的值会赋给那个变量 ~~~ def match2() = { for (c <- "+-*/123") { c match { case value if Character.isDigit(c) => println("这是一个数字: " + value) case '+' => println("这次字符为+号") case '-' => println("这次字符为-号") case '*' => println("这次字符为*号") case '/' => println("这次字符为/号") case _ => println("通配") } } } match2() ~~~ # 提取器 模式匹配什么才算匹配呢? 即,case中unapply方法返回some集合则为匹配成功,返回none集合则为匹配失败. **unapply** 调用unapply,传入number 接收返回值判断返回值是None还是Some 如果是Some,则将其解开,并将其中值赋值给n(就是case Square(n)中的n) ~~~ object Square { def unapply(z: Double): Option[Double] = Some(math.sqrt(z)) } object CaseDemo2 extends App { var n = 36.0 n match { case Square(result) => println(s" ${n} + ",s" + ${result}") } } ~~~ 输出 ~~~ ( 36.0 + , + 6.0) ~~~ # 变量声明中的模式 match中每一个case都可以单独提取出来,意思是一样的 ~~~ val (x, y) = (1, 2) println(x, y) val (q, r) = BigInt(10) /% 3 println(q, r) val arr = Array(1, 7, 2, 9) val Array(first, second, _*) = arr println(first, second) ~~~ 输出 ~~~ (1,2) (3,1) (1,7) ~~~ # for表达式中的模式 ~~~ import scala.collection.JavaConverters._ for ((k, v) <- System.getProperties.asScala) { println(k + " -> " + v) } ~~~ # 中置表达式 什么是一个中置表达式? 1+2,这就是一个中置表达式. 如果unapply方法产出一个元组,你可以在case语句中使用中置表示法.比如可以匹配一个List序列 ~~~ val list = List(1, 2, 3, 4, 5, 6) list match { case l1 :: l2 :: l3 => println(l1 + " , " + l2 + " , " + l3) } ~~~ 从左到有,多的就变为list 输出 ~~~ 1 , 2 , List(3, 4, 5, 6) ~~~ # 嵌套类 ~~~ abstract class Item case class Article(description: String, price: Double) extends Item //Item*表示可以多个 case class Bundle(description: String, discount: Double, item: Item*) extends Item object CaseDemo extends App { def match9() = { val sale = Bundle("愚人节大甩卖系列", 10, Article("<<九阴真经>>", 40), Bundle("从出门一条狗到装备全发光", 20, Article("如何快速捡起地上装备", 80), Article("名字起的太长", 30))) val result = sale match { case Bundle(_, _, Article(descr, _), _*) => descr } println(result) } match9() } ~~~ 输出 ~~~ <<九阴真经>> ~~~ 如果要输出后面可以这样 ~~~ val result = sale match { case Bundle(_, _, Article(descr, _), temp @ _*) => temp } ~~~ 输出 ~~~ WrappedArray(Bundle(从出门一条狗到装备全发光,20.0,WrappedArray(Article(如何快速捡起地上装备,80.0), Article(名字起的太长,30.0)))) ~~~ 通过@表示法将嵌套的值绑定到变量 `_*`绑定剩余Item到temp