Scala模式匹配
Scala中的模式匹配类似于java中的switch语法,但是java中的switch只能做分支运算,在Scala中的模式匹配能做更多。模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,并且跳出判断逻辑,如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case _分支,如果没有case _会抛出MatchError。
模式守卫
模式守卫实际就是对输入值的一个判断,后面可以加入类型之类的。如果满足则执行case之中的语句。9
def main(args: Array[String]): Unit = {
def abs(x :Int) = {
x match {
case i if i >=0 => i
case j if j <=0 => -j
case _ => "wrong value"
}
}
val value: Any = abs(-4)
println(s"value = ${value}")
}
匹配类型
匹配常量
def describe(x: Any) = x match {
case 5 => "Int five"
case "hello" => "String hello"
case true => "Boolean true"
case '+' => "Char +"
case _ =>"not any thing"
}
匹配类型
object TestMatchClass {
def describe(x: Any) = x match {
case i: Int => "Int"
case s: String => "String hello"
case m: List[_] => "List"
case c: Array[Int] => "Array[Int]"
// 代替的是下划线
case someThing => "something else " + someThing
}
def main(args: Array[String]): Unit = {
//在类型匹配时不考虑泛型
println(describe(List(1, 2, 3, 4, 5)))
//数组例外,可保留泛型,Array之所以例外是由于其在字节码中使用的是String[3]构造的数组
println(describe(Array(1, 2, 3, 4, 5, 6)))
println(describe(Array("abc")))
}
}
匹配数组
object TestMatchArray {
def main(args: Array[String]): Unit = {
for (arr <-
Array(Array(0),
Array(1, 0),
Array(0, 1, 0),
Array(1, 1, 0),
Array(1, 1, 0, 1),
Array("hello", 90))) {
val result = arr match {
case Array(0) => "0" //匹配Array(0) 这个数组
case Array(x, y) => x + "," + y //匹配有两个元素的数组,然后将将元素值赋给对应的x,y
case Array(0, _*) => "以0开头的数组" //匹配以0开头和数组
case _ => "something else"
}
println("result = " + result)
}
}
}
匹配列表
object TestMatchList {
def main(args: Array[String]): Unit = {
//list是一个存放List集合的数组
//请思考,如果要匹配 List(88) 这样的只含有一个元素的列表,并原值返回.应该怎么写
for (list <- Array(List(0), List(1, 0), List(0, 0, 0), List(1, 0, 0), List(88))) {
val result = list match {
case List(0) => "0" //匹配List(0)
case List(x, y) => x + "," + y //匹配有两个元素的List
case List(0, _*) => "0 ..."
// 把数据分为三段
case first :: second :: rest => println(first + "-" + second + "-" + rest)
case _ => "something else"
}
println(result)
}
}
}
匹配元组
object TestMatchTuple {
def main(args: Array[String]): Unit = {
//对一个元组集合进行遍历
for (tuple <- Array((0, 1), (1, 0), (1, 1), (1, 0, 2))) {
val result = tuple match {
case (0, _) => "0 ..." //是第一个元素是0的元组
case (y, 0) => "" + y + "0" // 匹配后一个元素是0的对偶元组
case (a, b) => "" + a + " " + b
case _ => "something else" //默认
}
println(result)
}
}
}
模式匹配的应用场景
object ScalaMatch02 {
def main(args: Array[String]): Unit = {
val list = List(("hello1", 1, 20), ("hello2", 1, 20), ("hello3", 1, 30))
for ((word, no, 20) <- list) {
println(word)
}
val stringToInt = Map(("a", 1), ("b", 2), ("c", 3))
// val stringToInt1: Map[String, Int] = stringToInt.map((s: (String, Int)) => {
// (s._1, s._2 * 2)
// })
// 在参数只有一个的场合可以使用模式匹配
// 使用模式匹配时需要将方法的小括号变为大括号
// case不能省略
val stringToInt1: Map[String, Int] = stringToInt.map{
case (word,count) => {
(word, count * 2)
}
}
// 取下划线大于等于2
println(stringToInt1)
}
}
object ScalaMatch05 {
def main(args: Array[String]): Unit = {
// 只会对满足条件的一部分数据做操作,并不会对所有的数据做操作
// 将集合中Int类型的元素加一,并去掉字符串
val list: List[Any] = List(1, 2, 3, 4, 5, "Int")
val list1: List[Any] = list.map(s => {
s match {
case num: Int => num + 1
case d => d
}
})
val list2: List[Any] = list1.filter(data => data.isInstanceOf[Int])
}
}
样例类
package cn.lpc.Cheapter08
// 样例类,作用就是为了模式匹配
// 和普通类的声明方式不一样
object ScalaMatch04 {
def main(args: Array[String]): Unit = {
}
}
// case class UserMatch(){
//
// }
// 样例类使用case关键字声明
// 样例类构造参数列表不能省略
// 当类声明为样例类时,编译器会自动生成伴生类和伴生对象
// 样例类和普通一致,在里面定义的apply方法是一个普通方法
// 样例类如果声明构造参数,等同于声明类的属性,而且该属性不可改变
// 等同于普通类在class UserMatch(val name : String){},可以修改修饰符号
// 工作中声明的类,一般声明样例类。
/*case class Student( name : String){
def say()={
println(name)
}
}*/
匹配对象
def mian():Unit {
//匹配对象时,首先会将对象传递到类的伴生对象的unapply方法。
// unapply方法会返回Opthion类型的数据,然后进行数据对比,如果全部比对成功,那么会执行对应的逻辑
// 在Scala中采用样例类可以更简单,不需要自定义unapply方法
val user :User = User("zhangsan", 11)
var result = user match{
case User("zhangsan", 11) =>"yes"
case => "no"
}
}
偏函数
函数只对满足条件的数据进行操作,不会对所有数据进行操作 在Scala中可以使用case可以简写偏函数
// 与map不同的的地区在于可以不要对不满足的数据做操作,map需要对全量数据做操作
list.collect{
case num:Int=>num+1
}
异常
object Scala_Exception {
def main(args: Array[String]): Unit = {
// Scala中采用的异常也是模式匹配
// Scala中异常没有分类,所以不需要再编译时提示
// 而且也不需要显示的用try,catch进行捕捉
// 一般将范围小的异常放置在前面捕捉,范围大的放置在后面
val i = 0
try{
val s = 10 /i
}catch {
case e :ArithmeticException => println("除数为0")
case ex : Exception => println("捕捉到异常")
}
}
}