1. 模式匹配
1.1. 更好的 Switch
Scala 中类似 Java 的 switch 代码:
object PatternDemo {
def main(args: Array[String]): Unit = {
var sign = 0
val ch: Char = 'p'
val valchar = 'p'
var digit = 0
//match 是表达式
ch match {
case '+' => sign = 1
case '-' => sign = -1
//使用|分割多个选项
case '*' | 'x' => sign = 2
//可以使用变量
case valchar => sign = 3
//case _ 类似Java中的default
// 如果没有模式能匹配,会抛出MacthError
//可以给模式添加守卫
case _ if Character.isDigit(ch) => digit = Character.digit(ch, 10)
}
println("sign = "+ sign)
}
}
1.2. 样例类匹配
//定义样例类
abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification
//基于样例类的模式匹配
def showNotification(notification: Notification): String = {
notification match {
case Email(email, title, _) =>
s"You got an email from $email with title: $title"
case SMS(number, message) =>
s"You got an SMS from $number! Message: $message"
case VoiceRecording(name, link) =>
s"you received a Voice Recording from $name! Click the link to hear it: $link"
}
}
val someSms = SMS("12345", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
println(showNotification(someSms)) //结果:You got an SMS from 12345! Message: Are you there?
println(showNotification(someVoiceRecording)) //结果:you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123
1.3. 带守卫的模式
增加布尔表达式使得匹配更具体。
def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
notification match {
//仅匹配email在importantPeople列表里的内容
case Email(email, _, _) if importantPeopleInfo.contains(email) =>
"You got an email from special someone!"
case SMS(number, _) if importantPeopleInfo.contains(number) =>
"You got an SMS from special someone!"
case other =>
showNotification(other) // nothing special, delegate to our original showNotification function
}
}
val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")
val someSms = SMS("867-5309", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
val importantSms = SMS("867-5309", "I'm here! Where are you?")
println(showImportantNotification(someSms, importantPeopleInfo))
println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
println(showImportantNotification(importantEmail, importantPeopleInfo))
println(showImportantNotification(importantSms, importantPeopleInfo))
1.4. 类型匹配
val arr = Array("hello", 1, 2.0, 'a')
val obj = arr(Random.nextInt(4))
obj match {
case x: Int => x
case s: String => Integer.parseInt(s)
case _: BigInt => Int.MaxValue
case _ => 0
}
1.5. 匹配数组、列表、元组
数组匹配
val arr1 = Array(1,1)
val res = arr1 match {
case Array(0) => "0"
//匹配包含0的数组
case Array(x, y) => s"$x $y"
// 匹配任何带有两个元素的数组,并将元素绑定到x和y
case Array(0, _*) => "0..."
//匹配任何以0开始的数组
case _ => "something else"
}
列表匹配
val lst = List(1,2)
val res2 = list match {
case 0 :: Nil => "0"
case x :: y :: Nil => x + " " + y
case 0 :: tail => "0 ..."
case _ => "something else"
}
元组匹配
var pair = (1,2)
val res3 = pair match {
case (0, _) => "0 ..."
case (y, 0) => s"$y 0"
case _ => "neither is 0"
}
2. Sealed 类 (密封类)
Scala 中,Traits 和 class 可以被关键字 Sealed 修饰,被该关键字修饰后,它所有的子类都必须在同一文件中被定义。
sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture
//此时无需定义能匹配所有的类型了
def findPlaceToSit(piece: Furniture): String = piece match {
case a: Couch => "Lie on the couch"
case b: Chair => "Sit on the chair"
}
3. 样例类
在 Scala 中样例类是一中特殊的类,样例类是不可变的,可以通过值进行比较,可用于模式匹配。
定义一个样例类:
case class Point(x: Int, y: Int)
创建样例类对象:
val point = Point(1, 2)
val anotherPoint = Point(1, 2)
val yetAnotherPoint = Point(2, 2)
通过值对样例类对象进行比较:
if (point == anotherPoint) {
println(point + " and " + anotherPoint + " are the same.")
} else {
println(point + " and " + anotherPoint + " are different.")
}
// Point(1,2) 和 Point(1,2)一样的.
if (point == yetAnotherPoint) {
println(point + " and " + yetAnotherPoint + " are the same.")
} else {
println(point + " and " + yetAnotherPoint + " are different.")
}
// Point(1,2)和Point(2,2)是不同的.
在模式匹配中使用样例类:
abstract class Amount
// 继承了普通类的两个样例类
case class Dollar(value: Double) extends Amount
case class Currency(value: Double, unit: String) extends Amount
case object Nothing extends Amount
object CaseClassDemo {
def main(args: Array[String]): Unit = {
val amt = new Dollar(10);
patternMatch(amt)
}
def patternMatch(amt: Amount) {
amt match {
case Dollar(v) => println("$" + v)
case Currency(_, u) => println("Oh noes, I got " + u)
case Nothing => println("nothing") //样例对象没有()
}
}
}
声明样例类 ,以下几件事会自动发生:
(1) 构造器中每一个参数都是 val,除非显示地声明为 var
(2) 伴生对象提供 apply ,让你不使用 new 关键字就能构造出相应的对象
(3) 提供 unapply 方法,让模式匹配可以工作
(4) 生成 toString,equals,hashCode,copy 方法,除非显示给出这些方法的定义。
4. Option 类型
在 Scala 中 Option 类型样例类用来表示可能存在或也可能不存在的值( Option 的子类有 Some 和 None )。Some 包装了某个值,None 表示没有值。
object OptionDemo {
def main(args: Array[String]) {
val map = Map("a" -> 1, "b" -> 2)
val v = map.get("b") match {
case Some(i) => i
case None => 0
}
println(v)
//更好的方式
val v1 = map.getOrElse("c", 0)
println(v1)
}
}
5. 偏函数
被包在花括号内没有 match 的一组 case 语句是一个偏函数,它是 PartialFunction[A, B] 的一个实例,A 代表参数类型,B 代表返回类型,常用作输入模式匹配。
object PartialFunctionDemo {
def f: PartialFunction[String, Int] = {
case "one" => 1
case "two" => 2
// case _ => -1
}
def main(args: Array[String]) {
//调用f.apply("one")
println(f("one"))
println(f.isDefinedAt("three"))
//抛出MatchError
println(f("three"))
}
}
本文为原创文章,如果对你有一点点的帮助,别忘了点赞哦!比心!如需转载,请注明出处,谢谢!