Scala_模式匹配

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 的两倍!

相关推荐