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)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值