一、什么是模式匹配

模式匹配:

如其它编程语言的 switch case 语句,对一个值进行条件判断,对不同的条件进行不同的处理

二、基础模式匹配

object MatchApp extends App {
  val names = Array("黄老师", "陆老师", "李老师")

  // 随机取出一个
  val name  = names(Random.nextInt(names.length))

  name match {
    case "黄老师" => println("姓黄")
    case "陆老师" => println("姓陆")
    case "李老师" => println("姓李")

    case _ => println("未知姓")
  }
}

多条件判断

object MatchApp extends App {
  def judgeGrade(name:String, grade:String): Unit ={
    grade match{
      case "A" => println("A...")  // #1
      case "B" => println("B...")  // #2
      case "C" => println("C...")  // #3

      case _ if(name == "lisi") => println("name is lisi")  // #4
      case _ => println("....") // #5
    }
  }

  judgeGrade("zhangsan", "A")  // 匹配到:#1
  judgeGrade("lisi", "B")      // 匹配到:#2
  judgeGrade("lisi", "D")      // 匹配到:#4

}

三、数组匹配

object MatchApp extends App {
  def greeting(array: Array[String]): Unit ={
    array match{
      case Array("zhangsan") => println("Hi:zhangsan")  // 只能匹配到数组里面只有一个元素是 zhangsan 的
      case Array(x, y) => println("Hi:" + x + ", " + y) // 匹配任意数组,是两个元素的
      case Array("zhangsan", _*) => println("Hi:zhangsan and other friends ...." ) // 匹配第一个元素是 zhangsan 的
      case _ => println("Hi: everybody ...")
    }
  }

  greeting(Array("zhangsan"))
  greeting(Array("lisi", "wangwu"))
  greeting(Array("zhangsan", "lisi", "wangwu"))
  greeting(Array("A", "B", "C"))
}

四、List匹配

Array 很像,注意匹配顺序

object MatchApp extends App {
  def greeting(list: List[String]): Unit = {
    list match {
      case "zhangsan" :: Nil  => println("Hi:zhangsan")
      case x :: y :: Nil      => println("Hi:" + x + y)
      case "zhangsan" :: tail => println("Hi: zhangsan and other friends ...")
      case _                  => println("Hi: everybody ...")
    }
  }

  greeting(List("zhangsan"))
  greeting(List("lisi", "wangwu"))
  greeting(List("zhangsan", "lisi", "wangwu"))
  greeting(List("A", "B", "C"))
}

五、类型判断

object MatchApp extends App {
  def matchType(obj:Any): Unit ={
    obj match {
      case i:Int => println("Int")
      case s:String => println("String")
      case m:Map[_,_] => m.foreach(println)
      case _ => println("other type")
    }
  }
  matchType(1)
  matchType("1")
  matchType(Map("name" -> "Pk"))
}

输出

Int
String
(name,Pk)

六、异常处理

object ExceptionApp extends App {
  try{
    val i = 10 / 0
    println(i)
  }catch {
    case e:ArithmeticException => println("除数不能为0")
    case e:Exception => println("除数不能为0")
  }finally {
    // 释放资源等操作,一定能执行的
  }
}

七、case class

case class 是用于与 case 表达式进行模式匹配的“特殊类”
在语法上,这些是带有特殊“修饰符”的标准类:case

还有 case object,和 case class 类似

object MatchApp extends App {
  def caseClassMatch(person: Person): Unit ={
    person match {
      case CTO(name, floor) => println("CTO name is:" + name + ", floor is " + floor)
      case Employee(name, floor) => println("Employee name is:" + name + ", floor is " + floor)
      case _ => println("Other...")
    }
  }

  // 定义类
  class Person
  case class CTO(name: String, floor:String) extends Person
  case class Employee(name: String, floor:String) extends Person
  case class Other(name: String) extends Person

  // 调用
  caseClassMatch(CTO("Pk", "10"))
  caseClassMatch(Employee("zhangsan", "2"))
  caseClassMatch(Other("other"))
}
object Demo {
   def main(args: Array[String]) {
      val alice = new Person("Alice", 25)
      val bob = new Person("Bob", 32)
      val charlie = new Person("Charlie", 32)

      for (person <- List(alice, bob, charlie)) {
         person match {
            case Person("Alice", 25) => println("Hi Alice!")
            case Person("Bob", 32) => println("Hi Bob!")
            case Person(name, age) => println(
               "Age: " + age + " year, name: " + name + "?")
         }
      }
   }
   case class Person(name: String, age: Int)
}

八、option 匹配

Option 类型中的模式匹配

  • Option 类型有两个子类,分别是 SomeNone(单例对象)
  • None 是一个case object,它同 Some 一样都 extends Option 类,只不过 Somecase class

对比反编译之后的代码可以看出

  • case object 对应反编译后的 CaseObject$.class 中不存在applyunapply 方法
  • 这是因为None不需要创建对象及进行内容提取,从这个角度讲,它被定义为case object是十分合理的
object OptionDemo {
  def main(args: Array[String]): Unit = {

    val map = Map("hadoop" -> 1, "spark" -> 2, "flink" -> 3)

    //scala 语言可以在一个函数中定义另外一个函数
    def mapPattern(key: String): Unit = {

      //get(key)方法中,通过key值获取与之相对应的value值
      map.get(key) match {
        case Some(x) => println(x); x
        case None => println("None"); -1
      }

    }

    mapPattern("hive")
    mapPattern("spark")
  }
}