Scala-模式匹配
模式匹配
简介
-
类似于java中switch
-
当数据满足某一个分支时,执行完毕后,就直接跳出
-
case分支类似于default语言, 分支匹配其实就是顺序匹配
-
如果数据没有匹配任何规则,会发生错误
// val age = 20 // // age match { // //case _ => println("other") // case 10 => println("age = 10") // case 30 => println("age = 30") // } var a: Int = 10 var b: Int = 20 var operator: Char = "+" var result = operator match { case "+" => a + b case "-" => a - b case "*" => a * b case "/" => a / b case _ => "illegal" }
匹配规则
匹配常量
def describe(x: Any) = x match {
case 5 => "Int five"
case "hello" => "String hello"
case true => "Boolean true"
case "+" => "Char +"
}
匹配类型
- 类型前增加变量名称,这个变量就是将数据转换成指定类型的变量
- 如果想要使用下划线代表的数据,可以给下划线起名来使用
def describe(x: Any) = x match {
case i : Int => i + 10
case s : String => "String hello"
case m: List[_] => "List"
case c: Array[Int] => "Array[Int]"
case someThing => "something else " + someThing
}
-
scala中类型匹配时,是不考虑泛型的,但是Array类型是特殊的。
-
类型匹配注意
Array[Int], 这里的Int不是真正的泛型
java中的写法 => String[]
scala中的写法 => Array[String]Array[Int] 是一个整体
List[Int] 是类型加泛型
不考虑泛型演示
case m: List[Int] => "List" println(describe(List("1", "2", "3"))) ==> List case m: List[string] => "List" println(describe(List(1, 2, 3))) ==> List
-
匹配数组
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)
}
result = 0
result = 1,0
result = 以0开头的数组
result = something else
result = something else
result = hello,90
匹配列表
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 _ => "something else"
}
println(result)
}
0
1,0
0 ...
something else
something else
匹配元组
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)
}
0 ...
10
1 1
something else
匹配对象
通过伴生对象定义unapply方法来进行对象之间的相互匹配
def main(args: Array[String]): Unit = {
// TODO - 模式匹配 - 匹配规则
// 匹配对象
// apply : Attribute => Object
val user = getUser()
// unapply : Object => Attribute
user match {
case User("zhangsan",40) => println("用户为张三")
case _ => println("什么也不是")
}
}
class User {
var name:String = _
var age:Int = _
}
object User {
// Object => Attribute
def unapply(user: User): Option[(String, Int)] = {
Option( (user.name, user.age) )
}
// Attribute => Object
def apply( name : String, age:Int ) = {
val user = new User()
user.name = name
user.age = age
user
}
}
def getUser() = {
User("zhangsan", 30)
}
模式匹配用法
- 直接取元组value
val (_, name, _) = (1, "zhangsan", 30)
println(name) ==> zhangsan
- 直接取map的key
val map = Map(
("a", 1), ("b", 2), ("c", 3)
)
for ( (k, 2) <- map ) {
println( k ) ==> b
}
- 用模式匹配去替换 ‘_ ‘ 加索引
val list = List(
(("河北", "鞋"), 10),
(("河北", "衣服"), 20),
(("河北", "电脑"), 15),
)
list.map(
(t) => {
t
}
)
// 下面的代码中,使用模式匹配需要注意:
// 1. 匹配数据时,需要使用case关键字
// 2. case分支可能存在多个,那么需要将map的小括号换成大括号
val list1 = list.map {
case ((prv, item), cnt) => {
(prv, (item, cnt * 2))
}
}
样例类
在编译时,会自动生成大量的方法
- 样例类会自动实现可序列化接口
- 样例类的构造参数直接能够作为属性使用,但是不能修改,如果想要修改,需要将参数使用var声明
- 增加和重写了大量的方法
- 样例类自动生成伴生对象,而且其中自动声明了apply,unapply
def main(args: Array[String]): Unit = {
val user = getUser()
user.name = "lisi"
user match {
case User("zhangsan",40) => println("用户为张三")
case _ => println("什么也不是")
}
}
case class User(var name:String, age:Int)
def getUser() = {
User("zhangsan", 40)
}
偏函数
以偏概全
-
全量函数 :函数进行处理时必须对所有的数据进行处理。
val list = List(1,2,3,4) // map只支持全量函数操作 // 1 => 2 // 2 => Unit // 3 => 6 // 4 => Unit val list1 = list.map( num => { if ( num % 2 != 0 ) { num * 2 } } ) println(list1) ==> List(2, (), 6, ())
-
偏函数 : 函数进行处理时只对满足条件的数据进行处理
// 将该List(1,2,3,4,5,6,"test")中的Int类型的元素加一,并去掉字符串 val list : List[Any] = List(1,2,3,4,5,6,"test") val list1 = list.map { case i : Int => { // 只匹配Int类型 i + 1 } case other => other }.filter(_.isInstanceOf[Int]) println(list1) val list : List[Any] = List(1,2,3,4,5,6,"test") val list1 = list.collect{ case i : Int => i + 1 } println(list1)