简介
与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