Scala专题系列 (八) : 模式匹配

2022-04-18 14:00:54 浏览数 (1)

模式匹配包括一系列备选项,每个替代项以关键字大小写为单位。每个替代方案包括一个模式和一个或多个表达式,如果模式匹配,将会进行评估计算。箭头符号=>将模式与表达式分离。

模式匹配的类型分为 :

  • 常量模式匹配
  • 变量模式匹配
  • 构造器模式
  • 序列模式
  • 元组模式
  • 变量绑定模式

模式匹配 - 常量模式

所谓常量模式匹配就是在case后面跟着的是常量,如同java中的swich语句

实例 :

代码语言:javascript复制
object Demo{
    def main(args:Array[String]){
  matchTest(1)
  matchTest("two")
 }
    def matchTest(x:Any):Any = x.match{
     case 1 => "one"
     case "two" => 2
     case _ => 0
 }
}

上面例子中,创建一个单例Demo,里面包含一个函数matchTest,并且参数类型是Any(scala中所有类的超类,表示任意类型), 注意看函数体 x = match{ case 1 => "one" } 这个就是scala中模式匹配的语法结构, 首先变量.match(选择器) 后面跟着一个花括号, 括号里面case指定的匹配项 , 而 => 右面指定的是表达式 , 在语句中 case _ 等同于java中swich语句的default ,如果匹配项都不符合要求,那么就返回一个默认值

模式匹配 - 变量模式

所谓常量模式匹配就是在case后面跟着的是变量

实例 :

代码语言:javascript复制
object Demo{
    def main(args:Array[String]){
  matchTest(1)
  matchTest("two")
 }
    def matchTest(x:Any):Any = x.match{
     case x if(x == "1") => "one"
     case x if(x =="two") => 2
     case _ => 
 }
}

变量匹配,匹的是case语句后面接的是scala变量,如case x if(x == "1") => x等,在使用时一般会加守卫条件(if(...)在模式匹配中就是一个守卫,类型是一个boolean),当然也可以像case x => x这样使用,它会匹配任何输入的合法变量 , 最后case _ => 等于一个default

模式匹配 - 构造器模式

构造器模式匹配直接在case语句后面接类构造器,匹配的内容放置在构造器参数中。

代码语言:javascript复制
case class Person(name : String,age : Int) // 定义一个样板类,下面会有样板类的具体介绍.
object Demo{
    def main(args:Array[String]){
  getPerson("liubin",24) 
 }
    def getPerson(p:Person) = p.match{
     case Person(name,age) => name   " , "   age 
     case _ =>  "other"
 }
}

在声明样例类时,下面的过程自动发生了:

  • 构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
  • 在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
  • 提供unapply方法使模式匹配可以工作;
  • 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。

模式匹配-序列化模式

序列模式用于匹配如数组Array、列表List、Range这样的线性结构集合,其实原理也是通过case class起作用的。

代码语言:javascript复制
object SequencePattern{
  def main(args:Array[String]) :Unit = {
    val list = List("spark","Hive","SparkSQL")
    val arr = Array("SparkR","Spark Streaming","Spark MLib")
  def pattern(p : Any) = p match {
    //序列模式匹配,_*表示匹配剩余内容,first、second匹配数组p中的第一、二个元素
    case Array(x,y,_*) => x   ","   y
    //_匹配数组p的第一个元素,但不赋给任何变量
    case List(_,y,_*) => y
    case _ => "Other"
  }
  }
}

上述实例实例中,第一个模式匹配Array中第一个和第二个元素,以及后面的所有元素,_*表示剩余内容,第二模式匹配List中的第二个元素, _ 表示匹配List中的第一个元素,但是不赋值给变量

模式匹配-元组模式

元组是一种类似于集合的存储结构,不过集合是可变的,元组是不可变的,元组的声明方式:val t = new Tuple3(1,“2”,’3’)上面就是声明了一个Tuple3[Int,String,Char]类型的元组,元组的访问可以用t._1来访问第一个元素,依次类推,元组中最多可有22个元素,如果元素个数大于22,就只能使用集合了。

元组模式用于匹配scala中的元组内容,用于匹配元组类型的变量内容。

代码语言:javascript复制
object TuplePattern{
  def main(args:Array[String]) :Unit = {
    val t = (“1”,“2”,3)
  def pattern(t : Any) = t match {{
    case (one,_,_) => one 
    case _ => "Other"
  }
  println(pattern(t))
  }
}

上述代码中,

//_*不适合用于元组,只适用于序列

模式匹配-类型模式

类型模式即根据参数的类型来匹配表达式

代码语言:javascript复制
object Demo{
    def main(args:Array[String]){
  matchTest(1)
 }
    def matchTest(x:Any):Any = x.match{
     case s:String => "String"
     case x:Int => “Int”
     case _ => 0
 }
}

在上面代码中,模式匹配到的值被当作String绑定到了s中,而在第二个模式中,值被当作Int绑定到x中;

当在匹配类型的时候,必须给出一个变量名,否则将会拿对象本身来匹配。

匹配是发生在运行时,Java虚拟机中泛型的类型信息时被擦掉的,因此不能用类型来匹配特定的Map 类型

比如:

case m:Map[String,Int] => … // 是不可行的

可以匹配一个通用的映射

caase m:Map[_,_] => ….

模式匹配分类总结:

通配模式(_):匹配任意对象,它被用作默认的“全匹配(catch-all)”的备选项

常量模型:仅匹配自身,任何字面量都可以用作常量

变量模式:类似于通配模式,它可以匹配任意对象。与通配符(_)不同的是,Scala把变量绑定在匹配的对象上。

构造器模式:提供了深度匹配(deep match),如果备选项是样本类,那么构造器模式首先检查对象是否为该备选项的样本类实例,然后检查对象的构造器参数是否符合额外提供的模式。

序列模式:可以像匹配样本类那样匹配如List或者Array这样的序列类型。

元组模式:匹配元祖

类型模式:匹配变量的类型

Option 类型

Option类型在Scala程序中经常使用,可以将其与Java中可用的null值进行比较,表示null值。 例如,java.util.HashMap的get方法返回存储在HashMap中的值,如果没有找到值,则返回null。

假设我们有一种基于主键从数据库中检索记录的方法。

def findPerson(key: Int): Option[Person]

Scala

如果找到记录,该方法将返回Some [Person],如果没有找到该记录,则返回None

0 人点赞