简介
与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 CheckTimeOutTaskobject 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" => 1case "two" => 2case _ => -1}//其他方式实现def func2(num: String): Int = num match {case "one" => 1case "two" => 2case _ => -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,并加1def 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 f1println(result)}
守卫
像if表达式一样,match也提供守卫功能,守卫可以是任何boolean条件
val ch = 3var sign = 0ch match {case '+' => sign = '+'case '-' => sign = '-'case _ if ch.toString.equals("3") => sign = 3case _ => 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.0n 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) /% 3println(q, r)val arr = Array(1, 7, 2, 9)val Array(first, second, _*) = arrprintln(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 Itemcase class Article(description: String, price: Double) extends Item//Item*表示可以多个case class Bundle(description: String, discount: Double, item: Item*) extends Itemobject 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
