基本语法
Scala模式匹配类似Java中的switch语法
var result = operator match {
case '+' => a + b
case '-' => a -b
case _ => 'illegal'
}
object Test {
def main(args: Array[String]): Unit = {
// 实现二元运算
val a = 25
val b = 13
def matchDua(op: Char): Any = op match {
case '+' => a+b
case _ => "非法运算符"
}
println(matchDua('+'))
}
}
- 如果所有都不匹配,那么会执行case 分支类似default。 如果没有case会抛出异常
- 每个case不需要break
- 可以匹配任何类型
=>后面的代码块,直到下一个case之前的代码作为一个整体执行,可以不用括号
模式守卫
如果想要匹配某个范围,可以增加条件守卫
object Test {
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 _ => "type illegal"
}
println(abs(-5))
}
}
模式匹配类型
匹配类型
object Test {
def main(args: Array[String]): Unit = {
// 匹配常量
def describeConst(x: Any): String = x match {
case 1 => "Num one"
case "hello" => "String hello"
case true => "Boolean true"
case '+' => "Char +"
case _ => "" // 表示什么都不做,_不是通配符,是占位符,写成 case abc => "" 也行
}
// 匹配类型
def dsecribeType(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 => "Something else: " + a // 如果兜底case还想返回类型,不用_形式(获取与当前值无关的返回)
}
val result = a match { //不需要用到具体的匹配项,可以用下划线代替
case _: String => "String"
case _: Int => "Int"
case _ => "未匹配"
}
println(describeType(34))
println(describeType("hello"))
println(describeType(list("hi","hello")))
println(describeType(list(2,3))) // 也匹配上了,泛型擦除,不会考虑泛型
println(describeType(Array("hi","helli"))) // 数组比较底层,会考虑类型,不会泛型擦除
println(describeType(Array(2, 23)))
// 匹配数组
for (arr <- List(
Array(0),
Array(1,0),
Array(0,1,0),
Array(1,1,0),
Array("Hellp",23)
)) {
val result = arr match {
case Array(0) => "0"
case Array(1,0) => "Array(1,0)"
case Array(x, y) => "Array" + x + ", " + y // 匹配两元素数组
case Array(0, _*) => "以0开头个数未知的数组"
case Array(x, 1, z) => "中间为1的三元素数组"
case _ => "something else"
}
}
// 匹配列表
for (list <- List(
List(0), //0
List(1,0), // List(x, y): 1, 0
List(0,0,0), // List(0,...)
List(1,1,0), // something else
List(88) // List(a): 88
List("hello") //List(a): hello
)) {
val result = list match {
case List(0) => "0" //case 0 :: Nil => ...
case List(x, y) => "List(x, y): " + x + ", " + y //case x :: y :: Nil =>...
case List(0, _x) => "List(0,...)" //case 0 :: tail => ...
case List(a) => "List(a):" +a
case _ => "something else"
}
println(result)
}
// 方式二
val list = List(1,2,5,7)
list match {
case first :: second :: rest => println(s"firset: $first, second: $second, rest: $rest")
// first: 1, second: 2, rest: List(5,7)
case _ => println("something else")
}
// 匹配元组
for (tuple <- List(
(0, 1),
(0, 0),
(0, 1, 0),
(0, 1, 1),
(1, 23, 56),
("hello", true, 0.5)
)){
val result = tuple match {
case (a, b) => "" + a + ", " + "b"
case (0, _) => "(0, _)"
case (a, 1, _) => "(a, 1, _)" + a
case _ => "something else"
}
}
}
}
元组的匹配
```scala // 在变量声明时匹配 val (x, y) = (10, “hello”) println(s”x: $x, y: $y”)
val List(first, second, _*) = List(23, 15, 9, 78) println(s”first: $first, second: $second”) //first: 23, second: 15 val fir :: sec :: rest = List(23,15,9,78) println(s”first: $fir, second: $sec, rest: $rest”)
// for推导式中进行模式匹配 val list: List[(String, Int)] = List((“a”, 12), (“b”, 35), (“c”, 27))
// 1.原本的遍历方式 for (elem <- list) { println(elem._1 + “ “ + elem._2) }
//2.将List元素直接定义为元组,对变量赋值 for((word, count) <- list) { println(word + “: “ + count) }
// 3.不考虑某个位置的变量,只遍历key或value for ((word, _) <- list) { println(word)//a b c }
// 4 可以指定某个位置的值必须是多少 for ((“a”, count) <- list){ println(count) // 12 }
<a name="CA0Pa"></a>
#### 变量声明中的模式匹配
```scala
def main(args: Array[String]): Unit = {
val arr1 = (0 to 10).toArray
val Array(_, x, y, z, _*) = arr1 //模式匹配匹配第234个元素
println(x, y, z)
val list1 = (0 to 10).toList
val List(a, b, _*) = list1 //匹配前两个
val c :: d :: tail = list1 //匹配前两个
匹配对象
object Test {
def main(args: Array[String]): Unit = {
val student = new Student("alice", 18)
// 针对对象实例匹配
val result = student match {
case new Student("alice", 18) => "Alice, 18"
case _ => "else"
}
}
}
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))
}
}
}
样例类
object Test {
def main(args: Array[Strint]): Unit = {
val student: Any = Student("alice", 18)
val result = student match {
case new Student("alice", 18) => "Alice, 18" //匹配具体内容
case _ => "else"
}
println(result) // Alice 18
val student2: Any = Student("jack",20)
val result2 = student2 match {
case Student(a,b) => println("匹配成功") //匹配类型
case _ => println("未匹配")
}
}
// 定义样例类
// 对应的伴生对象、apply、unapply方法自动生成
case class Student(name: String, age: Int) // 参数默认都是类的属性,不需要加val了
Option
避免空指针异常
- Some(x)表示实际值
- None表示没有值
```scala
def divede(a: Int, b: Int): Option[Int] = {
if (b == 0)
elseNone
}Some(a/b)
def main(args: Array[String]): Unit = { val result = divede(10, 0) match { case Some(x) => println(s”赏为:${x}”) case None => println(“出书不能为0”) }
// 方法二 println(result.getOrElse(“除数不能为0”)) }
<a name="J3KdA"></a>
### 偏函数
```scala
val pf: PartialFunction[Int, String] = { // Int参数类型,String返回类型
case 1 => "yi"
case 2 => "er"
case _ => "wei pi pei"
}
println(pf(1)) // yi
object Test {
def main(args: Array[String]): Unit = {
val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27))
// 1. map 转换 ,实现key不变,value2倍
val newList = list.map( tuple => (tuple._1, tuple._2 * 2))
// 2. 用模式匹配对元组元素赋值
val newList2 = list.map(
tuple => {
tuple match {
case (word, count) => (word, count * 2)
}
}
)
// 3. 省略lambda表达式
val newList3 = list.map {
case (word, count) => (word, count * 2)
} // 偏函数
}
}
object Test{
def main(args: Array[String]): Unit = {
// 对输入数据分为不同的情形: 正、负、0
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(-67)) //67
}
}
提取器
指的就是unapply方法
样例类自动实现了unapply
class Student(var name: String, var age: Int)
object Student {
// apply根据给定的字段,封装成Student类型对象
def apply(name: String, age: Int) = new Student(name, age)
// unapply根据传入的学生对象获取属性
def unapply(s: Student) = {
if(s == null)
None
else
Some(s.name, s.age)
}
}
def main(args: Array[String]):Unit = {
val s1 = new Student("张三", 23)
val s2 = Student("李四", 24)
//方式一
println(s1.name,s1.age)
//方式二
val result = Student.unapply(s1)
println(result)
//方式三 如果没有unapply方法,会报错,必须有提取器
s1 match {
case Student(name, age) => println(s"${name}, ${age}")
case _ => println("未匹配")
}
}