模式匹配是Scala中非常有特色,非常强大的一种功能。模式匹配,其实类似于Java中的swich case语法,即对一个值进行条件判断,然后针对不同的条件,进行不同的处理。
但是Scala的模式匹配的功能比Java的swich case语法的功能要强大地多,Java的swich case语法只能对值进行匹配。但是Scala的模式匹配除了可以对值进行匹配之外,还可以对类型进行匹配、对Array和List的元素情况进行匹配、对case class进行匹配、甚至对有值或没值(Option)进行匹配。
而且对于Spark来说,Scala的模式匹配功能也是极其重要的,在spark源码中大量地使用了模式匹配功能。因此为了更好地编写Scala程序,并且更加通畅地看懂Spark的源码,学好模式匹配都是非常重要的。
1、模式匹配的基础语法(案例:成绩评价)
object test
{
def main
(args
: Array
[String]): Unit = {
def studentScore
(score
:String): Unit ={
score
match {
case "A"=>println
("excellent")
case "B"=>println
("good")
case "C"=>println
("soso")
case _
=>println
("you need work harder")
}
}
studentScore
("D")
}
}
在模式匹配中使用
if守卫
object test
{
def main
(args
: Array
[String]): Unit = {
def studentScore
(name
:String,score
:String): Unit ={
score
match {
case "A"=>println
("excellent")
case "B"=>println
("good")
case "C"=>println
("soso")
case _
if name
=="leo"=>print
(name
+",you are good boy,come on!")
case _
=>println
("you need work harder")
}
}
studentScore
("leo","D")
}
}
在模式匹配中进行变量赋值
object test
{
def main
(args
: Array
[String]): Unit = {
def studentScore
(name
:String,score
:String): Unit ={
score
match {
case "A"=>println
("excellent")
case "B"=>println
("good")
case "C"=>println
("soso")
case _
if name
=="leo"=>print
(name
+",you are good boy,come on!")
case _score
=>println
("you need work harder,your score only "+_score
)
}
}
studentScore
("le","F")
}
}
2、对类型进行模式匹配(案例:异常处理)
object test
{
def main
(args
: Array
[String]): Unit = {
import java
.io
._
def processException
(e
: Exception
) {
e
match {
case e1
: IllegalArgumentException
=> println
("you have illegal arguments! exception is: " + e1
)
case e2
: FileNotFoundException
=> println
("cannot find the file you need read or write!, exception is: " + e2
)
case e3
: IOException
=> println
("you got an error while you were doing IO operation! exception is: " + e3
)
case _
: Exception
=> println
("cannot know which exception you have!" )
}
}
processException
(new IOException
("not such file"))
}
}
3、对Array和List的元素进行模式匹配(案例:对朋友打招呼)
object test
{
def main
(args
: Array
[String]): Unit = {
def greeting
(arr
: Array
[String]) {
arr
match {
case Array
("Leo") => println
("Hi, Leo!")
case Array
(girl1
, girl2
, girl3
) => println
("Hi, girls, nice to meet you. " + girl1
+ " and " + girl2
+ " and " + girl3
)
case Array
("Leo", _
*) => println
("Hi, Leo, please introduce your friends to me.")
case _
=> println
("hey, who are you?")
}
}
greeting
(Array
("Leo","lily","poly","jack"))
}
}
object test
{
def main
(args
: Array
[String]): Unit = {
def greeting
(list
: List
[String]) {
list
match {
case "Leo" :: Nil
=> println
("Hi, Leo!")
case girl1
:: girl2
:: girl3
:: Nil
=> println
("Hi, girls, nice to meet you. " + girl1
+ " and " + girl2
+ " and " + girl3
)
case "Leo" :: tail
=> println
("Hi, Leo, please introduce your friends to me.")
case _
=> println
("hey, who are you?")
}
}
greeting
(List
("Leo","jack","poly","herry"))
}
}
4、case class与模式匹配(案例:学校门禁)
class Person
case class Teacher
(name
:String,subject
:String) extends Person
case class Student
(name
:String,classroom
:Int) 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 entranceGuard
(p
:Person
): Unit ={
p
match {
case Student
(name
,classroom
)=>println
(s
"hello,$name,welcome to school,your classroom is $classroom")
case Teacher
(name
,subject
)=>println
(s
"hello,$name,welcome to school,your teach $subject")
case Worker
(name
,work
) if work
=="repairman"=>println
(s
"hello,$name,you should leave school afternoon")
case Worker
(name
,work
)=>println
(s
"hello,$name,you should leave school 2 hours later")
case _
=>println
(s
"stranger,you can not into school")
}
}
entranceGuard
(Worker
("Jason","cleaner"))
}
}
5、Option与模式匹配(案例:成绩查询)
object test
{
def main
(args
: Array
[String]): Unit = {
val grades
= Map
("Leo" -> "A", "Jack" -> "B", "Jen" -> "C")
def getGrade
(name
: String) {
val grade
= grades
.get
(name
)
grade
match {
case Some
(grade
) => println
("your grade is " + grade
)
case None
=> println
("Sorry, your grade information is not in the system")
}
}
getGrade
("J")
}
}
练习:
传递一个参数,A打印very good,B打印good,C打印just soso,使用守护,aaa打印good boy,其余打印study bad
object demoMatch
{
def match4
(x
:String):Unit=x
match{
case "A" =>println
("very good")
case "B" =>println
("good")
case "C" => println
("just soso")
case _
if x
=="aaa" =>println
("good boy")
case _
=>println
("study bad")
}
def main
(args
: Array
[String]): Unit = {
match4
("aaa")
}
}
在匹配模式中使用已定义的变量+在模式匹配中进行变量赋值:
https://stackoverflow.com/questions/7078022/why-does-pattern-matching-in-scala-not-work-with-variables
object demoMatch
{
def metch5
(name
:String,score
:String):Unit={
val target
:String="A"
score
match{
case `target`
=> println
("very good study")
case "B" => println
("good study")
case "C" => println
("just soso")
case _
if name
=="bonb" => println
("good boy")
case _score
=> println
("you must study hard, your score is "+ _score
)
}
}
def main
(args
: Array
[String]): Unit = {
metch5
("zhangsan","A")
}
}
match 的必须是 stable identifier ,如果要使用已定义的变量,可以加反引号或者使用大写字母开头的变量。
// Scala的模式匹配语法,有一个特点在于,可以将模式匹配的默认情况,下划线,替换为一个变量名,此时模式匹配语法就会将要匹配的值赋值给这个变量,从而可以在后面的处理语句中使用要匹配的值 // 为什么有这种语法??思考一下。因为只要使用用case匹配到的值,是不是我们就知道这个值啦!!在这个case的处理语句中,是不是就直接可以使用写程序时就已知的值! // 但是对于下划线_这种情况,所有不满足前面的case的值,都会进入_这种默认情况进行处理,此时如果我们在处理语句中需要拿到具体的值进行处理呢?那就需要使用这种在模式匹配中进行变量赋值的语法!!
异常处理
import java
.io
.FileNotFoundException
object demoMatch
{
def match6
(e
:Exception
):Unit={
e
match {
case e1
:IndexOutOfBoundsException
=> println
("IndexOutOfBoundsException")
case e2
:FileNotFoundException
=> println
("FileNotFoundException")
case e3
:NullPointerException
=> println
("NullPointerException")
case _
:Exception
=> println
("Exception")
}
}
def main
(args
: Array
[String]): Unit = {
match6
(new FileNotFoundException
())
}
}
传递不同的参数匹配不同的结果
object demoMatch
{
def match7
(arr
:Array
[String]):Unit={
arr
match {
case Array
("KB09") => println
("hello KB09")
case Array
(girl1
,girl2
,girl3
) => println
(s
"hello $girl1,$girl2,$girl3")
case Array
("KB09",_
*)=>println
("hello KB09*")
case _
=> println
("who are you?")
}
}
def main
(args
: Array
[String]): Unit = {
var arr
=Array
("KB09","KB07","KB05","KB02")
var arr1
=Array
("KB09")
var arr2
=Array
("KB09","KB07","KB05")
var arr3
=Array
("KB07","KB05","KB02","KB09")
match7
(arr
)
match7
(arr1
)
match7
(arr2
)
match7
(arr3
)
}
}
打印结果:
hello KB09*
hello KB09
hello KB09,KB07,KB05
who are you?
匹配不同的子类:
object demoMatch
{
class Person
case class Teacher
(name
:String,age
:Int) extends Person
case class Student
(name
:String,age
:Int) extends Person
case class Worker
(name
:String,age
:Int) extends Person
case class msr
(name
:String,age
:Int) extends Person
def match8
(p
:Person
):Unit={
p
match{
case Teacher
("zs",21) => println
("zs 年龄为21岁的老师找到了")
case Teacher
("zs",age
) => println
("zs老师的年龄为:"+age
)
case p1
:Teacher
=> println
(p1
.name
+" "+p1
.age
)
case p2
:Student
=> println
(p2
.name
+""+p2
.age
)
case p3
:Worker
if p3
.name
=="repairWorker" => println
("修理工")
case p4
:Worker
=> println
("普通工人")
case _
=>println
("不熟悉,不知道什么人")
}
}
def main
(args
: Array
[String]): Unit = {
val p1
=Worker
("zhangsan",21)
val p2
=Worker
("repairWorker",19)
val p3
=Teacher
("zs",23)
val p4
=Teacher
("zs",21)
match8
(p1
)
match8
(p2
)
match8
(p3
)
match8
(p4
)
}
}
匹配option类型,Some和None
object demoMatch
{
val map
=Map
("zs"->"a","ls"->"b","ww"->"c")
def match9
(name
:String):Unit={
var score
=map
.get
(name
)
score
match{
case Some
(score
) => println
(name
+"的成绩为"+score
)
case None
=> println
("没有"+name
+"对应的成绩")
}
}
def main
(args
: Array
[String]): Unit = {
match9
("zs")
match9
("pq")
}
}