Scala模式匹配详解

  • Post author:
  • Post category:其他




scala模式匹配

模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。

match 对应 Java 里的 switch,但是写在选择器表达式之后。Scala的模式匹配除了可以对值进行匹配之外,还可以对类型进行匹配、对Array和List的元素情况进行匹配、对case class进行匹配、甚至对有值或没值(Option)进行匹配。

match 表达式通过以代码编写的先后次序尝试每个模式来完成计算,只要发现有一个匹配的case,剩下的case不会继续匹配。

对于Spark来说,Scala的模式匹配功能也是极其重要的,在spark源码中大量地使用了模式匹配功能。



1.基本语法

match case语法最基本的应用,就是对变量的值进行模式匹配

def match1(x:Int):String=x match{
   case 1=>"one"
   case 2=>"two"
   case _=>"other"   //其他选项用 "_"表示
}
println(match1(1))  //输出one



2.类型匹配

Scala模式匹配可以直接对类型匹配

def match1(x:Any) =x match{
    case i:Int =>println("输入的值类型为Int类型,值为:"+i)
    case j:String =>println("输入的值类型为String类型,值为:"+j)
    case _ =>println("输入类型未知")
}
match1(2)  //输入得值类型为Int类型,值为:2

案例:对异常进行匹配

def excepetionmatch(e:Exception)=e match{
  case e1:IOException => println("error,IOException")
  case e2:NullPointerException=> println("error,NullPointerException")
  case e3:ClassNotFoundException=> println("error,ClassNotFoundException")
  case _:Exception=> println("don't know")
}
excepetionmatch(new IllegalArgumentException)



3.使用if守卫

Scala的模式匹配语法,有一个特点在于,可以在case后的条件判断中,不仅仅只是提供一个值,而是可以在值后面再加一个if守卫,进行双重过滤

def match1(name:String,score:String) =score match{
  case "A"=> println("perfect")
  case "B"=> println("good")
  case "C"=> println("just so so")
  case _ if name=="Li" => println(name+",请再接再厉")
  case _=> println("未及格")
}
match1("Li","F")
/*  Scala的模式匹配语法,有一个特点在于,可以将模式匹配的默认情况,下划线,替换为一个变量名,
   此时模式匹配语法就会将要匹配的值赋值给这个变量,从而可以在后面的处理语句中使用要匹配的值
   但是对于下划线_这种情况,所有不满足前面的case的值,都会进入_这种默认情况进行处理,
   此时如果我们在处理语句中需要拿到具体的值进行处理,那就需要使用这种在模式匹配中进行变量赋值的语法.*/
def match2(name:String,score:String) =score match{
  case "A"=> println("perfect")
  case "B"=> println("good")
  case "C"=> println("just so so")
  case _ if name=="Li" => println(name+",请再接再厉")
  case _score=> println(name+"get "+_score+" 未及格,") //变量赋值
}
match2("Li","D")



4.对Array和List的元素进行模式匹配

对Array进行模式匹配,分别可以匹配带有指定元素的数组、匹配指定个数元素的数组、以某元素开头的数组

 def match1(arr: Array[String])=arr match {
    case Array("Mike") => println("Hello,Mike")
    case Array(s1,s2,s3) => println("hello"+","+s1+","+s2+","+s3)
    case Array("Mike",_*) => println("hi")
    case _ => println("hi,what's your name")
  }
  var arr1=Array("Mike","Jim","Lucy","jeson") //定义Array
  var arr2=Array("Mike")
  var arr3=Array("Jim","Mike","Lucy")
  var arr4=Array("Jim","Lucy","Mike","jeson")
match1(arr1)  //对以mike开头的数组匹配  输出:hi
match1(arr2)  //对指定元素的数组进行匹配 输出:Hello,Mike
match1(arr3)  //对指定个数元素的数组进行匹配 输出 hello,Jim,Mike,Lucy
match1(arr4)  //未知数组匹配  输出:hi,what's your name



5.case class与模式匹配

Scala中可以使用case class声明样例类,并根据输入的样例类的类型来进行匹配

//定义一个case class
class Person
case class Teachers(name:String) extends Person
case class Student(name:String) extends Person
case class Worker(name:String,work:String)  extends Person
case class Stranger() extends Person

object test {
  def main(args: Array[String]): Unit = {
    def matchclass(p:Person)=p match {
      case Teachers(name) => println("my name is" + name + ".I'm a teacher")
      case Student(name) => println("my name is" + name + ".I'm a student")
      case Worker(name, work) if work == "repairman" => println("my name is" + name + ".I'm a repairman")  //同种类型使用if守卫需要放在前面
      case Worker(name, work) => println("my name is" + name + ".I'm a worker")
      case _ => println("hei,who are you?")
    }
    val p1=Teachers("张三") 
    val p2=Student("李四")
    val p3=Worker("王五","repairman")
    val p4=Worker("赵六","煤矿工")
    matchclass(p1)
    matchclass(p2)
    matchclass(p3)
    matchclass(p4)
  }
}

在这里插入图片描述



6.Option与模式匹配

Scala有一种特殊的类型,叫做Option。

Option有两种值,一种是Some,表示有值,一种是None,表示没有值。

Option通常会用于模式匹配中,用于判断某个变量是有值还是没有值,这比null来的更加简洁明了

Spark源码中大量地使用了Option,比如Some(a)、None这类语法.

val map=Map("Leo"->"A","Jack"->"B","Lucy"->"C")
  def match1(name:String)={
    val score=map.get(name)
    score match {
      case Some(grade)=> println(name+" get a "+grade)
      case None=> println("Sorry,"+name+" no grade")
    }
  }
  match1("Jac")  //输出 Sorry,Jac no grade
  match1("Jack")  //输出Jack get a B



版权声明:本文为timicai原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。