0%

scala模式匹配

scala模式匹配

scala的模式匹配与java中的switch…case类似,不过比switch要强大,模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需要匹配时, 会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下 一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
val operator = '*'
val num1 = 10
val num2 = 2
// => 后为执行的代码块,匹配到之后执行完代码块自动退出,不需要break
// 如果没有匹配到,则执行case _ 默认操作
val result = operator match {
case '+' => num1 + num2
case '-' => num1 - num2
case '*' => num1 * num2
case '/' => num1 / num2
case '%' => num1 % num2
case _ => throw new Exception("操作错误")
}

// 20
println(result)

模式匹配不只是可以判断值是否匹配,还可以进行类型匹配,根据值所对应的类型进行不同的操作

1
2
3
4
5
6
7
8
9
val list = List(1,"aaa",3.0)
for(item <- list){
item match {
// 这里是将item赋值给a,再去判断类型的,如果后续用不到该变量,可以使用_
case a:Int => println("Int类型")
case b:String =>println("String类型")
case _ =>println("这是什么类型,怎么出现在我的集合里了")
}
}

条件守卫

有时进行匹配之后还要进行判断,但是模式匹配并不能执行两个case,匹配到一个就会退出,那么可以在模式匹配中增加模式守卫,匹配到之后再次进行一次条件判断,在case匹配后再加上一个if判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
val operator1 = '-'
val num3 = 3
val num4 = 15
val result1 = operator1 match {
case '+' => num3 + num4
// 由于不满足if条件num3 > num4,如果并没有执行该操作,继续向下匹配
case '-' if num3 > num4 => num3 - num4
case '*' => num3 * num4
case '/' => num3 / num4
case '%' => num3 % num4
case _ => throw new Exception("操作错误")
}

// java.lang.Exception: 操作错误
println(result1)

模式中的变量

如果case后跟着一个变量名,那么匹配的表达式会被赋值给这个变量

1
2
3
4
5
str(i) match {
case '+' => sign = 1
case '-' => sign = -1
case ch => digit = Character.digit(ch,10)
}

匹配数组

可以使用模式匹配来根据条件筛选出想要的数组

  • Array(0) 表示匹配只有一个元素且为0的数组
  • Array(x,y) 匹配数组有两个元素,并将两个元素赋值给x和y
  • Array(0,_*) 匹配第一个元素为0的数组
1
2
3
4
5
6
7
8
9
val array = Array(Array(0),Array(0,1,2),Array(3,4,5))

for(a <- array){
a match {
case Array(0) => println(s"${a}该数组只有一个0")
case Array(0,_*) => println(s"${a}该数组第一个元素为0")
case Array(x,y,z) => println(s"${a}该数组第一个元素不为0,且有三个元素,分别为$x $y $z")
}
}

List和元组也可以使用这种方式来操作

如元祖表示

1
2
3
4
5
pair match {
case (0,_) => "0 ..."
case (y,0) => y+" 0"
case _ => "不包含0"
}

类型匹配

1
2
3
4
5
6
7
obj match {
// 如果在匹配类型的时候没有变量名的话,会拿对象本身进行匹配 如 case Int => 1 表示匹配类型为Class的Int对象
case x:Int => x
case s:String => Integer.parseInt(s)
case _: BigInt => Int.MaxValue // 匹配任何类型为BigInt的对象
case _ => 0
}

对象匹配

在使用对象匹配时需要在对象的伴生对象中声明unapply方法来进行对象提取,根据对象提取返回的进行匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Student(uid: Int) {
var id: Int = uid
var name: String = _

def this(id: Int, name: String) = {
this(id)
this.name = name
}
}

object Student {
def unapply(stu: Student): Option[Int] = {
Some(stu.id)
}

def apply(id: Int) = {
new Student(id)
}

def apply(id: Int, name: String) = {
new Student(id, name)
}
}


val stu1 = Student(1,"张三")
val stu2 = Student(1,"李四")
val stu3 = Student(2,"张三")

val stuList = List(stu1,stu2,stu3)

for(stu <- stuList){
stu match {
// 会调用Student的unapply方法,来判断是否相等
case Student(1) => println(s"相同的学生${stu.id} ${stu.name}")
case _ => println(s"不是相同的学生${stu.id}")
}
}


// 输出
相同的学生1 张三
相同的学生1 李四
不是相同的学生2

欢迎关注我的其它发布渠道