14 模式匹配
14.1 match 语句
match 语句用在当需要从多个分支中进行选择的场景,类似于java 中的switch 语句。
语法:
变量 match{
case "值" => 语句块1 // 语句块后不用加break
case "值2" => 语句块2
case _ => 语句块N // 类似于java的default
}
其中:
1)case 后面的表达式可以是任何类型的常量,如字段串、类、元组、集合等;
2)与java的switch不同的是,match 结构中不需要break 语句来跳出判断;
3)最后一个case语句用了通配符“_”,相当于java的default;
4)如果匹配不到,就会报错;
14.2 字符串匹配
import scala.util.Random
object MatchDemo {
def main(args: Array[String]): Unit = {
var arr = Array("A","B","C","D")
val a = arr(Random.nextInt(arr.length))
println(a)
a match {
case "A" => println("a")
case "B" => println("b")
case "C" => println("c")
case _ => println("other")
}
}
}
14.3 类型匹配
match除了匹配特定的常量,还能匹配某种类型的所有值;
在scala 中倾向于用这样的模式匹配,而不是isInstanceOf 操作符;
package day03
import scala.util.Random
object MatchDemo2 {
def main(args: Array[String]): Unit = {
val arr: Array[Any] = Array(1, 100L, 3.14, "1000", Array[Int](1,2,3))
val data: Any = arr(Random.nextInt(arr.size))
var data2:Int = 0
// 用 match匹配类型
data match {
case x:Int => data2 = x
case x:Long => data2 = x.toInt
case x:Double => data2 = x.toInt
case x:String => data2 = x.toInt
case x:Array[Int] => data2 = x.sum
}
println(s"data:${data}, data2:${data2}")
// 这种多类型匹配不适合用 isInstanceOf, asInstanceOf
// if(data.isInstanceOf[Int]){
// data2 = data.asInstanceOf[Int]
// }else if(data.isInstanceOf[Long]){
// data2 = data.asInstanceOf[Long].toInt
// }
}
}
14.4 数组、元组、集合匹配
元组匹配时case后面的值的个数应与被匹配的元组中数据的个数相同,否则报错。
当有多个条件能匹配到时以最先匹配到的条件为准
object MatchDemo3 {
def main(args: Array[String]): Unit = {
val arr = Array(1, 2, 3, 4)
arr match {
case Array(1, x, y) => println(s"x:$x,y:$y")
case Array(_, x, y, d) => println(s"x:$x,y:$y,d:$d")
case _ => println("other")
}
val tuple = (5, 6, 7)
tuple match {
case (1, a, b) => println(s"case1 a:$a,b:$b")
case (3, a, b) => println(s"case2 a:$a,b:$b")
case (_, x, y) => println(s"case3 a:$x,b:$y")
case _ => println("other")
}
val list = List(7,8,9)
list match {
case 7 :: b :: Nil => println(s"case 1 b:$b")
case List(a,b,c) => println(s"case 2 a:$a,b:$b,c:$c")
case 7 :: 8 :: b :: Nil => println(s"case 3 b:$b")
case _ => println("other")
}
}
}
//-----------运行结果-----------------
x:2,y:3,d:4
case3 a:6,b:7
case 2 a:7,b:8,c:9
14.5 偏函数匹配
1)使用 case 语句构造匿名函数与偏函数。
// 构造匿名函数
val list = List(1,2,3)
// 下面三种方式同等效果
val list1 = list.map((x:Int) => x*2)
// 编译器把case语句翻译成普通函数
val list2 = list.map({case x:Int => x*2})
val list3 = list map {case x:Int => x*2}
// 当把case语句翻译成普通函数时,如果匹配不上会报错
val list4 = List(1,2,3,"aaa",4)
//这句就会报错
val list5 = list4 map {case x:Int => x * 2}
val list = List(1,2,3, "aaa", 4)
// collect 接收偏函数作为参数,此时把case语句作为参数传递,scala编译器会把 case 语句翻译成偏函数
// 当构造偏函数时,值匹配能匹配上的,不能匹配上的放弃并顾虑掉;
list.collect({case x:Int => x*2})
res10: List[Int] = List(2, 4, 6, 8)
总结:
当编译器把case语句翻译成函数时,如果匹配不上会报错;
当编译器把case语句翻译成偏函数时,匹配不上的放弃并过滤掉;
2)偏函数
在Scala中,所有偏函数的类型皆被定义为 PartialFunction[-A, +B] 类型,PartialFunction[-A, +B] 又派生自 Function1 。
PartialFunction[-A, +B] ,其中 A 是方法参数类型,B是方法返回值类型。
PartialFunction(偏函数)内部常与 case 语句搭配,进行模式匹配,函数体里的模式匹配没有match关键字;
当把偏函数作为函数使用时,如果匹配不上会报错;
当把偏函数作为偏函数时,匹配不上的放弃并过滤掉;
package day03
object MatchDemo3 {
// 定义普通方法
def m1(data:Any):Int = {
data match {
case x:Int => x * 10
// case x:String => x.toInt * 10
// case _ => 0
}
}
// 定义偏函数
def func:PartialFunction[Any, Int] = {
case x:Int => x * 10
}
def main(args: Array[String]): Unit = {
println(m1(10))
//println(m1("10"))
println(func(10))
val list = List(1,2,3, "aa", "bb")
// collect接收偏函数,func定义时只要Int
println(list.collect(func))
println(list.map(m1))
}
}
海汼部落原创文章,原文链接:http://hainiubl.com/topics/75746