赞
踩
Scala 中的模式匹配类似于 Java 中的 switch 语法,但是功能更强大
/** [var a = / def func() = ] var_name match { case value1 => statement1 case value2 => statement2 case value3 => statement3 case _ => defaultOP } */ object TestMatchCase { def main(args: Array[String]): Unit = { val a = 10 val b = 20 def matchCalculate(op: Char): Any = op match { case '+' => a + b case '-' => a - b case '*' => a * b case '/' => a / b case _ => "非法运算符" } println(matchCalculate('+')) println(matchCalculate('*')) println(matchCalculate('@')) } }
在模式匹配中增加条件守卫可以匹配某个范围的数据
object TestMatchGuard { def main(args: Array[String]): Unit = { // 使用模式守卫实现绝对值 def abs(num: Int): Int = { num match { case i: Int if i >= 0 => i case i: Int if i < 0 => -i } } println(abs(22)) println(abs(0)) println(abs(-18)) } }
模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等
object TestMatchTypes { def main(args: Array[String]): Unit = { def describe(x: Any): String = x match { case 1 => "Int one" case "hello" => "String hello" case true => "Boolean true" case '+' => "Char +" case _ => "" // _ 是占位符,可以用其他字符替代 } println(describe(1)) println(describe("hello")) println(describe(0.3)) } }
模式匹配可以实现类似 isInstanceOf[T] 和 asInstanceOf[T] 的功能
object TestMatchTypes { def main(args: Array[String]): Unit = { def describeType(x: Any): String = x match { case i: Int => "Int " + i case s: String => "String " + s case list: List[String] => "List " + list case array: Array[Int] => "Array[Int] " + array.mkString(",") case a => "other type " + a // 用 _ 占位不能获取到传入的变量,可以用其他字符替代 } println(describeType(1)) println(describeType("hello")) println(describeType(List("hello", "scala"))) println(describeType(List(2, 3))) // 可以匹配,scala 会做泛型擦除 println(describeType(Array("hello", "scala"))) // 不能匹配,Array 没有泛型擦除 println(describeType(Array(2, 3))) } }
模式匹配可以对集合进行精确的匹配,例如匹配只有两个元素的、且第一个元素为 0 的数组
object TestMatchTypes { def main(args: Array[String]): Unit = { val arrList: List[Array[Any]] = List( Array(0), Array(1, 0), Array(0, 1, 0), Array(1, 1, 0), Array(2, 3, 7 ,15), Array("hello", 20, 30) ) for(arr <- arrList) { var result = arr match { case Array(0) => "只有一个元素为 0 的数组" case Array(x, y) => "有两个元素的数组:" + x + ", " + y case Array(0, _*) => "第一个元素为 0 的数组" case Array(x, 1, y) => "中间元素为 1 的三元素数组" case _ => "other type" } println(result) } } }
object TestMatchTypes { def main(args: Array[String]): Unit = { val lists: List[List[Any]] = List( List(0), List(1, 0), List(0, 0, 0), List(1, 1, 0), List(1, 0, 0), List(88), List("hello") ) for(list <- lists) { var result = list match { case List(0) => "只有一个元素为 0 的列表" case List(x, y) => "有两个元素的列表:" + x + ", " + y case List(0, _*) => "第一个元素为 0 的列表" case List(x, 1, y) => "中间元素为 1 的三元素列表" case List(a) => "只有一个元素的列表:" + a case _ => "other type" } println(result) } } }
object TestMatchTypes { def main(args: Array[String]): Unit = { val list1 = List(1, 2, 3, 4, 5) val list2 = List(5) // first:1 second:2 rest:List(3, 4, 5) list1 match { case first :: second :: rest => println(s"first:$first second:$second rest:$rest") // 匹配有第一个和第二个元素的列表 case _ => println("other type") } // other type list2 match { case first :: second :: rest => println(s"first:$first second:$second rest:$rest") case _ => println("other type") } } }
object TestMatchTypes { def main(args: Array[String]): Unit = { val tupleList = List( (0), (0, 1), (1, 1), (0, 0, 1), (1, 1, 0), ("hello", true, 0.5) ) for(tuple <- tupleList) { val result = tuple match { case (0) => "只有一个元素 0 的元组" case (0, _) => "第一个元素为 0 的二元组" case (x, y) => "二元组:" + x + ", " + y case (a, 1, _) => "中间元素为 1 的三元组:" + a case (a, b, c) => s"三元组:$a $b $c" case _ => "other type" } println(result) } } }
// 定义一个类 class Student(val name: String, val age: Int) // 定义伴生对象 object Student { // 实现 apply 方法用于创建对象 def apply(name: String, age: Int): Student = new Student(name, age) // 实现 unapply 方法用于拆解对象属性 def unapply(student: Student): Option[(String, Int)] = { // Option 防止空指针 if(student == null) { None } else { Some((student.name, student.age)) } } } object TestMatchObject { def main(args: Array[String]): Unit = { // 创建对象 val student = new Student("tom", 18) // 对象模式匹配 val result = student match { // 对象匹配的是各属性是否相同而不是地址 // 不能使用 new 创建,且类的伴生对象必须实现 apply 和 unapply 方法 case Student("tom", 18) => "tom 18" case _ => "other" } println(result) } }
Student("tom", 18)
在执行时,实际调用的是伴生对象中的 apply 方法构造出相应的对象Student("tom", 18)
写在 case 后时会默认调用伴生对象中的 unapply 方法(对象提取器),该对象作为 unapply 方法的参数,在 unapply 方法中将该对象的 name 和 age 属性提取出来,与 new Student("tom", 18)
中的属性值进行匹配unapply(obj: ObjClass): Option[T]
;若提取对象的多个属性,则提取器为 unapply(obj: ObjClass): Option[(T1,T2,T3…)]
;若提取对象的可变个属性,则提取器为 unapplySeq(obj: ObjClass): Option[Seq[T]]
样例类简介
/**
定义语法:case class className(field1: type1, field2: type2,...)
特点:
1.样例类仍然是类,和普通类相比,只是自动生成了伴生对象且伴生对象中自动提供了一些常用的方法,如 apply、 unapply、 toString、 equals、 hashCode 和 copy
2.样例类是为模式匹配而优化的类,因为其默认提供了 unapply 方法,因此,样例类可以直接使用模式匹配,而无需自己实现 unapply 方法。
3.构造器中的每一个参数默认都为 val,除非它被显式地声明为 var(不建议这样做)
*/
case class User(name: String, age: Int) // 无需指定 val
实现对象模式匹配
// 定义样例类 case class User(name: String, age: Int) object TestMatchObject { def main(args: Array[String]): Unit = { val user = User("bob", 20) val result = user match { case User("bob", 20) => "bob 20" case _ => "other" } println(result) } }
object TestMatchVariable { def main(args: Array[String]): Unit = { // 使用模式匹配元组变量赋值 val (x, y, z) = (10, "hello", true) println(s"x:$x y:$y z:$z") // 使用模式匹配列表变量赋值 val List(first, second, _*) = List(2, 4, 7, 9) println(s"first:$first second:$second") val fir :: sec :: rest = List(2, 4, 7, 9) println(s"fir:$fir sec:$sec rest:$rest") // fir:2 sec:4 rest:List(7, 9) // 使用模式匹配对象属性赋值 val Person(name, age) = Person("zhangsan", 16) println(s"name=$name age=$age") } }
object TestMatchFor { def main(args: Array[String]): Unit = { val list: List[(String, Int)] = List(("a", 1), ("b", 4), ("c",3), ("a",4)) // 1. for循环直接赋值 KV for((k, v) <- list) { // (elem <- list) println(k + ": " + v) // println(elem._1 + ": " + elem._2) } // 2. for循环只遍历 key 或 value for((k, _) <- list) { // ((_, v) <- list) println(k) // println(v) } // 3. for循环遍历指定 key 或 value for(("a", v) <- list) { // ((k, 4) <- list) println("a: " + v) // println(k + ": 4") } } }
偏函数也是函数的一种,通过偏函数我们可以方便的对输入参数做更精确的检查
/**
val funcName: PartialFunction[inParamClass, outParamClass] = {
case value => statement
}
*/
// 定义一个获取列表第二个元素的偏函数
val getSecond: PartialFunction[List[Int], Option[Int]] = {
case first :: second :: _ => Some(second)
}
// 1. 定义的偏函数会被解析翻译 val getSecond: PartialFunction[List[Int], Option[Int]] = { case first :: second :: _ => Some(second) } // => val getSecond = new PartialFunction[List[Int], Option[Int]] { //检查输入参数是否合格 override def isDefinedAt(list: List[Int]): Boolean = list match { case first :: second :: _ => true case _ => false } //执行函数逻辑 override def apply(list: List[Int]): Option[Int] = list match { case first :: second :: _ => Some(second) } } // 2. 偏函数调用时采用 applyOrElse 方法,其逻辑为 if(ifDefinedAt(list)) apply(list) else default。如果输入参数满足条件,即 isDefinedAt 返回 true,则执行 apply 方法,否则执行 defalut 方法,default 方法为参数不满足要求的处理逻辑 getSecond.applyOrElse(List(1,2,3), (_: List[Int]) => None)
object TestPartialFunction { def main(args: Array[String]): Unit = { // 使用偏函数实现绝对值方法 val positiveAbs: PartialFunction[Int, Int] = { case x if x > 0 => x } val negativeAbs: PartialFunction[Int, Int] = { case x if x < 0 => -x } val zeroAbs: PartialFunction[Int, Int] = { case 0 => 0 } def abs(x: Int): Int = (positiveAbs orElse negativeAbs orElse zeroAbs)(x) println(abs(-22)) println(abs(18)) println(abs(0)) } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。