muhongdi 2020-05-12
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。
1.
package scalaprogram.May07
import scala.util.Random
//模式匹配 ---------- 升级版的switch语句
object PatternTest {
def main(args: Array[String]): Unit = {
//1、字符匹配
val charStr = ‘-‘
charStr match {
case ‘+‘ => println("匹配上了加号")
case ‘-‘ => println("匹配上了减号")
case ‘*‘ => println("匹配上了乘号")
case ‘/‘ => println("匹配上了除号")
//注意。所有的模式匹配都必须最终匹配上一个值,如果没有匹配上任何值,就会报错
case _ => println("都没有匹配上,我是默认值")
}
//2、 匹配字符串
val arr = Array("hadoop", "zookeeper", "spark")
val name = arr(Random.nextInt(arr.length))//随机获取arr数组中的一个字符串
name match {
case "hadoop" => println("大数据分布式存储和计算框架...")
case "zookeeper" => println("大数据分布式协调服务框架...")
case "spark" => println("大数据分布式内存计算框架...")
case _ => println("我不认识你...")
}
//3、守卫 guard
var ch = "500"
var sign = 0
ch match {
case "+" => sign = 1
case "-" => sign = 2
case _ if ch.equals("500") => sign = 3 //可以加一个过滤条件
case _ => sign = 4
}
println(ch + " " + sign)
//4、 匹配类型
//注意泛型擦除,在模式匹配当中的类型匹配中,除了Array类型以外,所有的其他的数据类型都会被擦除掉
val a = 3
val obj = if(a == 1) 1
else if(a == 2) "2"
else if(a == 3) BigInt(3)
else if(a == 4) Map("aa" -> 1) //键值对 键:aa 值:1
else if(a == 5) Map(1 -> "aa")
else if(a == 6) Array(1, 2, 3)
else if(a == 7) Array("aa", 1)
else if(a == 8) Array("aa")
val r1 = obj match {
case x: Int => x
case s: String => s.toInt
case BigInt => -1 //不能这么匹配 前面必须为一个变量 (泛型擦除)
case _: BigInt => Int.MaxValue
case m: Map[String, Int] => "Map[String, Int]类型的Map集合"
case m: Map[_, _] => "Map集合"
case a: Array[Int] => "It‘s an Array[Int]"
case a: Array[String] => "It‘s an Array[String]"
case a: Array[_] => "It‘s an array of something other than Int"
case _ => 0
}
println(r1 + ", " + r1.getClass.getName)
//5、匹配数组、元组、集合
val arr1 = Array(1, 3)
arr1 match {
case Array(0, x, y) => println(x + " " + y)
case Array(0) => println("only 0")
//匹配数组以1 开始作为第一个元素
case Array(1, _*) => println("0 ...")
case _ => println("something else")
}
val lst = List(0, 3, -1)
lst match {
case 0 :: Nil => println("only 0") // List(0) 即Nil是空List 双冒号是追加进入
case x :: y :: Nil => println(s"x: $x y: $y") //List(x,y)
case 0 :: tail => println("0 ...") //tail任意值
case _ => println("something else")
}
val tup = (1, 3, 7)
tup match {
case (1, x, y) => println(s"1, $x , $y")
case (_, z, 5) => println(z)
case _ => println("else")
}
}
}运行结果:
匹配上了减号 大数据分布式存储和计算框架... 500 3 2147483647, java.lang.Integer 0 ... 0 ... 1, 3 , 7
2.apply与unapply
package scalaprogram.May07
/**
* apply方法通常称为注入方法,在伴生对象中做一些初始化操作
* apply方法的参数列表不需要和构造器的参数列表统一
* unapply方法通常称为提取方法,使用unapply方法提取固定数量的参数来进行模式匹配
* unapply方法会返回一个序列(Option),内部产生一个Some对象,Some对象存放一些值
* apply方法和unapply方法会被隐式的调用
*/
object Apply_unapply {
def main(args: Array[String]): Unit = {
val currency = Currency(30.2, "EUR") //没有使用new 调用了Currency的apply方法
println("&&&&&&&&&&&&&&&&&&&&&&")
currency match {
//隐式调用了unapply方法,提取若干个参数进行模式匹配
case Currency(amount, "USD") => println("USD:" + amount)
//case Currency(amount, "EUR") => println("EUR:" + amount)
case _ => println("No match.")
}
}
}
class Currency(val value: Double, val unit: String) {}
object Currency{
def apply(value: Double, unit: String): Currency = {
println("apply()")
new Currency(value, unit)
}
def unapply(currency: Currency): Option[(Double,String)] = {
println("unapply()")
if (currency == null){
None
}
else{
Some(currency.value, currency.unit)
}
}
}运行结果:
apply() &&&&&&&&&&&&&&&&&&&&&& unapply() No match.
package scalaprogram.May07
object Test {
def main(args: Array[String]) {
println ("Apply 方法 : " + apply("Zara", "gmail.com"));
println ("Apply 方法 : " + Test("Zara", "gmail.com")); //通过类调用test的apply(user: String, domain: String)方法
println ("Unapply 方法 : " + unapply("")); //显式调用unapply方法
println ("Unapply 方法 : " + unapply("Zara Ali"));
val x = Test(5)
println(x)
x match {
case Test(num) => println(x + " 是 " + num + " 的两倍!") //case class
//unapply 被调用 (隐式调用)
case _ => println("无法计算")
}
}
def apply(x:Int): Int = {x * 2}
def unapply(z: Int): Option[Int] = {
println("unapply")
if (z%2 == 0)
Some(z/2)
else
None
}
// 注入方法 (可选)
def apply(user: String, domain: String) = {user +"@"+ domain}
// 提取方法(必选)
def unapply(str: String): Option[(String, String)] = {
val parts = str split "@"
if (parts.length == 2){
Some(parts(0), parts(1))
}else{
None
}
}
}运行结果:
Apply 方法 : Apply 方法 : Unapply 方法 : Some((Zara,gmail.com)) Unapply 方法 : None 10 unapply 10 是 5 的两倍!