Scala 模式匹配
1、基本使用
-
函数编程语言的标配
-
有点类似 java 的 switch
-
要匹配的值 match{
case 选项 =>
代码
case 选项 =>
代码}
object PatternDemo1 {
def main(args: Array[String]): Unit = {
val a:Int = 10
val b:Int = 20
val op:String = StdIn.readLine("请输入一个运算符")
op match{
case "+" =>
println(a+b)
case "-" =>
println(a-b)
case "*" =>
println(a*b)
case "/" =>
println(a/b)
case _ => //匹配其他所有的可能的情况,不能写在最前面
println("你的运算符输入不对")
}
}
}
2、匹配变量
object PatterDemo2 {
def main(args: Array[String]): Unit = {
val a:Int = 30
a match{
case 20 => println(20)
case aa => println(aa) //case语句新声明的变量,来任何东西都可以匹配
}
}
}
- aa 是新声明的,只能在这个case 内使用,与前面定义的变量不冲突
- 变量是大写字母开头,是一个常量,必须是以定义好的常量
- 可以使用 ’ ’ 进行反转(将 ‘aA’ == Aa)
- case _ 本质就是匹配变量,只是把变量的名字省略了
3、模式匹配的值
- 模式匹配也有值,它的值就是匹配成功的那个case的最后一行代码的值
object PatterDemo3 {
def main(args: Array[String]): Unit = {
val a:Int = 10
val b:Int = 20
val op:String = StdIn.readLine("请输入一个运算符")
val r :Int=op match{
case "+" =>
a+b
case "-" =>
a-b
case "*" =>
a*b
case "/" =>
a/b
case _ => -1//匹配其他所有的可能的情况,不能写在最前
}
println(r)
}
}
4、守卫和匹配类型
object PatterDemo4 {
def main(args: Array[String]): Unit = {
// val a:Any = 10
val a:Any = "abc"
a match{
case a:Int if a > 10 => println(a+10) //加守卫
case s:String => println(s.toUpperCase())
case b:Boolean => println(b)
case _ =>
}
}
}
object PatterDemo5 {
def main(args: Array[String]): Unit = {
//val arr:Array[Int] = Array[Int](1,2,3)
val arr:Any = List[Double](1.1,2,3)
arr match{
// case a:Array[Int] => println("Array[Int]")
// 下面这行代码编译不通过,Double一定匹配不了Int
// case a:Array[Double] => println("Array[Double]")
// case a:Array[_] => println("Array[_]")
case a:List[Int] => println("List[Int]")
//上面这行代码可以通过,泛型不管用
case a:List[_] => println("List[_]") //没有必要进行检查
}
}
}
注意:
- 数组在scala中表面用到了泛型,实际不是泛型
- 除了数组,其他所有泛型都是真正的泛型
- 泛型模式匹配是无法匹配除了泛型的类型的
- 泛型的存在是为了编译的时候类型更安全
- 泛型只存在于源码和编译的时候,编译成字节码之后,泛型就不存在了,这为:泛型擦除
5、匹配数组
object PatterDemo6 {
def main(args: Array[String]): Unit = {
val arr:Array[Int] = Array(2,2,3,4,10,5)
arr match{
case Array(1,2,_,_) =>println("Array(1,2,_,_)")
case Array(1,2,a,b) => println(a+b)
case Array(a,b,c,d) => println(a)
case Array(1,2,_*) => println("Array(1,2,_*)")
//上行代码只匹配数组第一个元素为1,第二个元素为2的数组,不管数组长度,与后面的值
case Array(2,2,abc@_*) => println(abc)//输出:Vector(3, 4, 10, 5)
}
}
}
6、元组匹配
object PatterDemo7 {
def main(args: Array[String]): Unit = {
val t:(String,Int) = ("lisi",20)
t match{
case (name,age) => println(name)
case (name:String,age) => println(name)
//case (name:Int,age) => println(name) 编译不通过
}
}
}
7、List匹配
object PatterDemo8 {
def main(args: Array[String]): Unit = {
val list:List[Int] = List(10,20,30,40)
list match{
// case List(10,20,c,d) => println(s"List(a,b,$c,$d)")
// case List(10,abc@_*) => println(abc)
// case a::b::c::d::Nil => println(a)
case a::rest =>println(rest) //将第一个元素赋给a,剩余元素赋给rest(ret是变量名)
case a::b::c =>println(c) //最后一个元素一定是 List集合
}
}
}
8、Option的使用
object OptionDemo1 {
def main(args: Array[String]): Unit = {
/*val op:Option[Int] = get
if(op.isDefined){
println(op.get)
}*/
val op:Option[Double] = sqrt(9)
if(op.isDefined) {
println(op.get)
}else{
println("没有平方根")
}
}
def sqrt(n:Double):Option[Double] ={
if(n >= 0) Some(math.sqrt(n))
else None
}
// def get:Option[Int] = Some(10) //把Some当成一个集合,只能存一个数字
def get:Option[Int] = None
}
object Pattern5 {
val opt:Option[Int] = Some(10)
val v = opt match{
case Some(x) =>
//更加复杂的逻辑
x
case None => 0
}
println(v)
}
9、模式匹配中的对象匹配
- 对象的 unapply 或 unapplySSeq
class People(val age:Int,val name:String)
object People{
def unapply(pp: People):Option[(Int, String)] =
if(pp != null)
Some(pp.age, pp.name)//Some 中只能封装一个值,此封装的是元组
else None
}
object ObjMatch {
def main(args: Array[String]): Unit = {
val p :People = new People(10,"zhiling")
p match{
case People(age,name) => println(age,name) //它会找 People 伴生对象的unapply
case _ =>
}
}
}
使用对象匹配的方式把一个数的平方根匹配出来
object Sqrt{
def unapply(d: Double):Option[Double] =
if(d >= 0) Some(math.sqrt(d))
else None
}
object ObjMath1 {
def main(args: Array[String]): Unit = {
//使用对象匹配的方式把一个数的平方根匹配出来
val d:Double = 9;
d match{
case Sqrt(a) => println(a)
}
}
}
10、匹配序列
object MyArray{
def unapplySeq(s:String) =
if(s != null)
Some(s.split(",").toList)
else None
}
object ObjMath2 {
def main(args: Array[String]): Unit = {
val names:String ="lisi,zhangsan,wangwu,zhiling,fengjie"
names match{
case MyArray(a,b,rest@_*) =>
println(a) //输出:lisi
println(b) //输出:zhangsan
println(rest) //输出:List(wangwu, zhiling, fengjie)
}
}
}
11、样例匹配
样例类将 apply、unapply、equals、hashCode …全实现了
case class User8(age:Int,name:String)
object CaseDemo1 {
def main(args: Array[String]): Unit = {
val user:User8 = User8(10,"lisi")
user match{
case User8(age,name) => println(age) // 顺序与构造器要一致
}
}
}
12、变量和循环中的模式匹配
object Pattern1 {
def main(args: Array[String]): Unit = {
val (a,b):(Int,String) = foo()
println(a)
println(b)
val Array(a1,b1,rest@_*) = foo1()
println(a1)
println(b1)
println(rest)
val list = List((1,2),(10,20),(100,200))
// for(kv <- list){
// println(kv._1)
// }
//替换上面
for((k,v) <- list){
println(k)
}
}
def foo() = (10,"lisi")
def foo1() = Array(1,2,3,4,5)
}