- Scala 模式匹配
- 一、模式匹配
- 1、基本语法
- 2、语法说明
- 3、案例示例
- 二、模式守卫
- 三、模式匹配类型
- 1、匹配常量
- 2、匹配类型
- 3、匹配数组
- 4、匹配列表
- 5、匹配元组
- 6、匹配对象及样例类
- (1) 基本语法
- (2) 优化case样例类
- 7、偏函数式的模式匹配(了解)
Scala 模式匹配 一、模式匹配
Scala 中的模式匹配类似于Java中的switch语法
,但是scala 从语法中补充了更多的功能,所以更加强大
模式匹配语法中,采用match
关键字声明,每个分支采用case
关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行相对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有的case都不匹配,那么会执行case…分支,类似于Java中的default
语句
(1) 如果所有case都不匹配,那么会执行case_
分支,类似于Java中的default
语句,若此时没有case_
分支,那么会抛出MatchError
(2) 每个case中,不需要使用break 语句,自动中断case
(3) match case 语句可以匹配任何类型,而不是字面量
(4) =>后面的代码块,直到下一个case 语句之前的代码是作为一个整体执行
,可以使用{}
括起来,也可以不括
package Scala04_moshipipei
//模式匹配基本语法
class test01_moshi {}
object test01_moshi{def main(args: Array[String]): Unit = {//1、基本语法定义
val x:Int = 10
val y:String = x match { case 1 =>"one" //如果为1那么返回的是one,中间是=>连接
case 2 =>"two"
case 3 =>"there"
case _ =>"这就是默认情况了,0"
}//判断x等于什么,如果x为1那么y就是one,如果x为2那么y就是two
println(y)
//2、示例;用模式匹配实现简单的二元运算
val a = 25
val b = 13
def hanshu(op:Char) = op match { case '+' =>a + b
case '-' =>a - b
case '*' =>a * b
case '/' =>a / b
case '%' =>a % b
case _ =>"非法运算符"
}
println(hanshu('*'))
println(hanshu('+'))
println("\\") //传一个字符进去,还要进行转义
}
}
二、模式守卫如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫
注意:num 就是 那个 i
,然后调用的时候传入参数进去就可以了
// 模式守卫
//求一个整数的绝对值
def fanfga(num:Int) = num match {//num就是下面的那个i
case i if i >= 0 =>i //定义一个i,如果i大于等于0就返回i
case i if i< 0 =>-i //如果小于0 那么输出-i,那肯定就是绝对值
}
println(fanfga(5))
println(fanfga(0))
println(fanfga(-5))
三、模式匹配类型Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。
推荐还是把case _
加上,因为写的条件可能就那么几个,要是写错了,就会报MatchError
//Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。
//1、匹配常量
def hanshu(x:Any):String = x match {//返回值不一定非得String,其他的也可以
case 1 =>"num one" //这就是返回值
case "hello scala" =>"String hello"
case true =>"Boolen true" //连布尔类型都可以
case '+' =>"Char +"
case _ =>"" //建议还是要设置一个这个,然后条件是有限的,传入参数要是没有就报错了
}
println(hanshu(1))
println(hanshu("hello scala"))
println(hanshu(true))
println(hanshu(0.3))
2、匹配类型Scala 不仅仅可以匹配常量,还可以匹配数据结构,比如列表,数组.
注意:类型匹配的时候要注意,比如定义了List[String]
泛型,规定的定义的是String
类型的,但是Int类型的还是匹配上了,因为Scala 的底层有泛型擦除
,他只会匹配到是一个list,泛型会自动擦除。而数组比较特殊,它是没有泛型擦除的,所以特别注意这两个地方,容易出现Bug
package Scala04_moshipipei
//模式匹配类型
class test02_pipeileixing {}
object test02_pipeileixing{def main(args: Array[String]): Unit = {//Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。
//1、匹配常量
def hanshu(x:Any):String = x match {//返回值不一定非得String,其他的也可以
case 1 =>"num one" //这就是返回值
case "hello scala" =>"String hello"
case true =>"Boolen true" //连布尔类型都可以
case '+' =>"Char +"
case _ =>"" //建议还是要设置一个这个,然后条件是有限的,传入参数要是没有就报错了
}
println(hanshu(1))
println(hanshu("hello scala"))
println(hanshu(true))
println(hanshu(0.3))
println("================")
//2、匹配类型
def hanshu2(x:Any):String = x match { case i:Int =>"int" + i //相当于前面规定了这个变量必须的是Int类型的才能匹配上
case i:String =>"String," + i
case list: List[String] =>"list:" + list //连List类型都可以定义
case array:Array[Int] =>"现在是第"+array.mkString(",")+"圈" //因为数组直接输出是引用,所以要用mkString方法输出
case a =>"Something else:" + a //这是兜底的方法,要拿到值的话就不能用 _ ,必要要设置一个变量
}
println(hanshu2(35))
println(hanshu2("hello"))
println(hanshu2(List("hi","hello")))
println(hanshu2(List(2,23)))
println(hanshu2(Array("hi","hello")))
println(hanshu2(Array(2,23)))
}
}
3、匹配数组Scala 模式匹配,匹配数组非常强大,可以进行各种模糊的匹配,比如可以匹配必须是三个元素,或者中为1的三个元素的数组。
//3、匹配数组
for (arr<- List(
Array(0),
Array(1,0),
Array(0,1,0),
Array(1,1,0),
Array(2,3,7,15),
Array("hello",20,30)
)){ val result = arr match { case Array(0) =>"0"
case Array(1,0) =>"1,0"
case Array(x,y) =>"Array:" + x + y //相当于可以进行模糊查询,匹配两元素数组
case Array(0,_*) =>"以0开头的数组"
case Array(x,1,z) =>"中间为1的三元素数组"
case _ =>"兜底的方法"
}
println(result)
}
4、匹配列表列表的匹配有两种方式,第一种和数组的匹配的方式是一样的,
第二种是:case first :: second :: rest =>println(s"first:${first} second:${second} rest
,rest是列表,first是第一个元素,second是第二个元素,表示这个列表中至少要有两个元素才能匹配到。列表的这种匹配方式非常常用。
//方式一
for(list<- List(
List(0),
List(1,0),
List(0,0,0),
List(1,1,0),
List(88),
List("hello")
)){ val result2 = list match {//这个list就是前面的那个list
case List(0) =>"0"
case List(x,y) =>"List(x,y):" + x + "," + y //这个x,y就是两个数的那个列表
case List(0,_*) =>"List(0,...)" //必须以0开头的列表。后面的个数不限*是通配符
case List(a) =>"List(a)" //表示list里面只有一个元素
case _ =>"something else"
}
println(result2)
}
println("=====================")
//方式二
//这种方式在列表匹配里面非常常用
val list = List(1,2,5,7,24)
val list1 = List(24)
list1 match { case first :: second :: rest =>println(s"first:${first} second:${second} rest ${rest}") //相当于rest是一个列表,第一个元素是first,第二个元素是second
case _ =>println("something else")
}
5、匹配元组元组的匹配跟之前的列表和数组的匹配是非常相似的
for(tuple<- List(
(0,1),
(0,0),
(0,1,0),
(1,23,56),
("hello",true,0.5)
)){ val result = tuple match {case (a,b) =>println(s"${a},${b}") //这就是一个二元组
case (0,_) =>println("0,_") //表示第一个元素是0,第二个元素不做要求的一个二元组
case (a,1,_) =>println("a,1,_"+ a) //表示中间那个元素必须是1,最后一个元素不关心
case _ =>"something"
}
println(result)
}
除此之外很有很多操作,很灵活
package Scala04_moshipipei
//元组匹配的扩展,元组的匹配是有一点特殊的,是很灵活的
class test03_MatchTuple {}
object test03_MatchTuple{def main(args: Array[String]): Unit = {//1、在变量声明时匹配
val (x,y) = (10,"hello")
println(s"${x},${y}")
val List(first,second,_*) = List(23,15,9,78) //把first赋值给了23,吧second赋值给了15
println(s"first:${first},second:${second}")
val fir :: se :: rest = List(23,15,9,78) //想要吧后面两个赋值给一个,那么还是::这种方法
println(s"first:${fir},second:${se},rest:${rest}")
//2、for推导式中进行模式匹配
val list:List[(String,Int)] = List(("a",12),("b",35),("c",27),("a",24))
for (i<- list){//使用增强for循环进行遍历
println(i._1 + " " + i._2)
}
//2.2 将List的元素直接定义为元组,对变量赋值
for((word,count)<- list){ println(word+ " " +count) //直接输出就可以了
}
println("=============")
//2.3 可以不考虑某个位置的变量,只遍历key或者value
for((word,_)<- list){ println(word) //这样就得到的全都是key了
}
println("==================")
//2.4 指定某个位置的值必须是多少
for (("a",count)<- list){ println(count) //把所有key是"a"对应的value值都打印出来
}
}
}
6、匹配对象及样例类
(1) 基本语法class User(val name:String,val age:Int)
这个可以说是一个非常强大的功能,通过伴生对象里面的值来进行匹配,伴生对象里面要有apply
方法,还要有unapply
方法,用来对对象属性进行拆解,不然会报错。
步骤简单来说就是,首先定义一个类,然后定义它的伴生对象,然后再伴生对象里面实现apply
方法,然后还要是先unapply
方法
package Scala04_moshipipei
class test04_Object {}
object test04_Object{def main(args: Array[String]): Unit = {val student = new Student("aex",18)
//针对对象实例的内容进行匹配
val result = student match { case Student("aex",18) =>"aex,18"
case _ =>"else"
}
println(result)
}
}
//定义类
class Student(val name:String,val age:Int){}
//定义一个伴生对象
object Student {def apply(name: String, age: Int): Student = new Student(name, age)
//必须实现一个unapply 方法,用来对对象属性进行拆解,这个方法名也是固定的了的,只能为这个
def unapply(student: Student): Option[(String, Int)] = {if (student == null) { None
} else { Some(student.name, student.age) //这样就拆分出来了
}
}
}
(2) 优化case样例类上面那种方式,虽然实现了,但是太繁琐了违背了scala简洁的定义,所以有了样例类,样例类的定义非常简单,直接在类的前面加上case
关键字
例如:case class Student1(val name:String,val age:Int){}
定义了样例类之后,就相当于自动实现了伴生类,apply方apply
法和unapply
方法,然后可以直接进行对象匹配了
package Scala04_moshipipei
//样例类,对象匹配的简化
class test05_yanglilei {}
object test05_yanglilei{def main(args: Array[String]): Unit = {val student = new Student1("aex",19)
val result = student match { case Student1("aex",19) =>"aex,18"
case _ =>"没有可以进行匹配的"
}
println(result)
}
}
//定义样例类 前面加一个case关键字就可以了
//定义了样例类,就相当于自动实现了伴生对象,apply方法和unapply方法
case class Student1(val name:String,val age:Int){}
7、偏函数式的模式匹配(了解)偏函数也是函数的一种,通过偏函数我们可以方便的对输入参做更精确的检查。例如该偏函数的输入类型为List[Int],而我们需要的是第一个元素是0的集合,这就是通过模式匹配实现的。
偏函数定义
package Scala04_moshipipei
//偏函数
class test06_PartialFunction {}
object test06_PartialFunction{def main(args: Array[String]): Unit = {val list = List(("a",12),("b",35),("c",27),("a",13)) //二元组
//1、map转换,实现key不变,value变成原来的2倍
val newList = list.map(a =>(a._1,a._2*2)) //下滑1第一个元素不变,第二个元素*2
println(newList)
//2、模式匹配也可以做这个操作,模式匹配对元组元素赋值,实现功能
val newList2 = list.map(
a =>{a match { case (word,count) =>(word,count*2) //直接这样就赋值了
case _ =>"没有匹配的"
}
}
)
println(newList2)
//3、省略lambda 表达式的写法,进行简化
val newList3 = list.map{ case (word,count) =>(word,count*2)
}
println(newList3)
//偏函数的应用,求绝对值
//对输入数据分为不同的情形:正,负,0
val zheng:PartialFunction[Int,Int] = {//输入的类型是Int,返回的类型也是一个Int
case x if x >0 =>x
}
//这是负数的偏函数
val fushu:PartialFunction[Int,Int] = {//输入的类型是Int,返回的类型也是一个Int
case x if x< 0 =>-x
}
//这是为0的情况
val zero:PartialFunction[Int,Int] = {//输入的类型是Int,返回的类型也是一个Int
case 0 =>0
}
def abs(x:Int):Int = (zheng orElse fushu orElse zero ) (x) //前面是作为一个整体
println(abs(-5))
println(abs(0))
println(abs(35))
}
}
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
网站题目:Scala模式匹配-创新互联
转载注明:http://lswzjz.com/article/descie.html