大数据8_09_Scala模式匹配

11 模式匹配

11.1 基本语法

Scala中的模式匹配类似于Java中的switch - case 语句。可以按照指定的规则对数据进行匹配。

  • 模式匹配主要用于规则匹配,模式匹配语法中没有break操作,执行完毕后,直接退出。

  • 模式匹配中的_下划线表示任意值,类似于java中的default操作

    但是不同的是java中的default操作,不管放在前面还是后面,都是最后执行。

    但是scala中的case _ 放在前面,后面的就执行不到了。

  • 模式匹配主要目的是将数据匹配上,必须匹配上,如果没有匹配条件会报错!

object Test1_Match {
  def main(args: Array[String]): Unit = {
    //TODO 匹配规则 - 基本语法
    print("please enter a word:")
    val str = scala.io.StdIn.readLine()

    val describe = str match {
      case "scala" => "SCALA"
      case "spark" => "SPARK"
      case "hadoop" => "HADOOP"
      case _ => "else subject"
    }
    println(describe)
  }
}

11.2 匹配常量

def describe(x: Any) = x match {
    case 5 => "Int five"
    case "hello" => "String hello"
    case true => "Boolean true"
    case '+' => "Char +"
}

11.3 匹配类型

  • 模式匹配中集合是不考虑泛型的

    也就是说List不管里面放什么类型的数据,只要它是List,那就能够匹配上。

  • 模式匹配中Scala的Array的泛型是特殊的

    可以理解为Array[String]和Array[Int]是两种不同的类型,因为Java中数组没有泛型的概念,编译成java后其实就是String[]和Int[]所以这是两个不同的类型。

    //TODO 匹配类型
    def describe(x: Any) = x match {
      case i: Int => s"${i} * 2 = ${i * 2}"
      case s: String => "type is String"
      case l: List[_] => "List do not have generic"
      case a: Array[String] => "Array[String] is a type"
      case e => "something else"
    }
    println(describe(10))
    println(describe("Tom"))
    println(describe(List(1, 2, 3)))
    println(describe(List("1", "2", "3")))
    println(describe(Array(1, "2", "3")))

11.4 匹配数组

    //TODO 匹配数组
    for (arr <- Array(
      Array(1),
      Array(0, 0, 1),
      Array('a', '3'),
      Array(1, 3),
      Array("hello", 90, 99, 100)
    )){
      val result = arr match {
        case Array(x) => "array has one param"
        case Array(0, _*) => "array started with 0, and other param"
          //这里的Array数组内不能放不同类型的数据,Array('a', 3),这样就不行。
          //因为数组只能放一种类型数据。比如String[],比如Char[]
        //这里是判断数组内的类型
        case Array(x: Char, _) => "array started type is char , and two param"
        case Array(x, y) => "array has two param"
        case _ => "something else"
      }
      println(result)
    }

11.5 匹配列表

    //TODO 匹配列表
    for (list <- Array(
      List(1),
      List(0, 0, 1),
      List('a', '3'),
      List('a', "name"),
      List(1, 9, 2)
    )){
      val result = list match {
        case List(x) => "list has one param"
        case List(0, _*) => "list start with 0, and other param"
        //可以匹配列表里的元素的类型
        case List(x: Char, y: String) => "list has two param, and first type is char , second type is string"
        case List(x, y) => "list has two param"
        case _ => "something else"
      }
      println(result)
    }

11.6 匹配元组

    //TODO 匹配元组
    for(tuple <- Array(
      (0, 1),
      (1, "string"),
      (1, 1, 3),
      (1, 2)
    )){
      val result = tuple match {
        case (0, _) => "start with 0, and tow param"
        case (x: Int, y: String) => "Int and String"
        case (1, _, 3) => "1, _, 3"
        case (_, 2) => "_, 2"
        case _ => "something else"
      }
      println(result)
    }

11.7 匹配对象

  • scala中匹配对象并不是真正的匹配对象,其实就是匹配对象的所有属性是否相同,

  • 对象属性的比较是scala编译器完成的,但是伴生对象中应该有一个unapply方法

    apply 方法是一个通过属性创建对象的过程

    unapply 方法是一个通过对象提取属性的过程

object Test1_Match_6 {
  def main(args: Array[String]): Unit = {
    //TODO 模式匹配 - 匹配对象
    val user = new User("Tom", 23)
    //scala中匹配对象并不是真正的匹配对象
    //所谓的匹配对象,其实就是匹配对象的所有属性是否相同
    //这里对象的属性比较由scala自动完成,但是需要遵循特殊的规则
    //伴生对象中应该有一个unapply方法

    //apply方法是一个通过属性创建对象的过程
    //unapply方法是一个通过对象提取属性的过程

    user match {
        //匹配对象中的所有属性!必须要有unapply方法
      case User("Tom", 213) => println("zhangsan用户")
      case _ => println("其他用户")
    }
  }

  class User(val name: String, val age: Int)
  object User{
    def apply(name: String, age: Int): User = new User(name, age)

    def unapply(arg: User): Option[(String, Int)] = {
      Option((arg.name, arg.age))
    }
  }
}
使用样例类的方式匹配对象
object Test1_Match {
  def main(args: Array[String]): Unit = {
    //TODO 匹配对象
    val user = User("Tom", 'M')
    user match {
      case User("Tom", 'F') => println("Tom")
      case _ => println("other user")
    }
  }
  case class User(var name: String, val gender: Char)
}

11.8 样例类

  • 样例类就是使用case关键字声明的类
  • 样例类仍然是类,和普通的类相比,只是自动生成了伴生对象,并且伴生对象内自动提供了:apply()、unapply()、toString()、equals()、hashCode()、copy()
  • 样例类在编译时,自动实现了可序列化接口
  • 一般情况下,样例类就是没有主题内容,
  • 样例类在构造对象时,构造参数可以不用声明为var和val,默认使用val,如果想改可以显示声明为var
object Test1_Match_7 {
  def main(args: Array[String]): Unit = {
    //TODO 模式匹配 - 样例类
//    val user = User   
    val tom = User("Tom", 24)
    val jerry = User.apply("Jerry", 42)

    tom match {
      case User("Tom", 23) => println(s"name=${tom.name}, age=${tom.age}")
      case _ => println("other user")
    }
  }
  //类前可以使用case关键字,这样的类称为样例类
  //样例类在编译时,自动实现了可序列化接口
  //样例类在编译时,自动生成伴生对象
  //样例类也是一个类,所以可以应用在任意场合
  //一般情况下,样例类就是没有主体内容
  //样例类构造对象时,构造参数可以不用声明为var或val,默认使用val
  //如果想要更改,那么可以声明为var
  case class User (val name: String, var age: Int)
}

11.9 应用场景

① 变量声明
    //TODO 应用场景
    val (id, name, age) = (1, "Tom", 23)
    println(s"id=${id}, name=${name}, age=${age}")
② 循环匹配
    val map = Map(("a", 1), ("b", 2), ("c", 3))
    //循环输出,赋值给k-v
    for ((k, v) <- map){
      println(k+v)
    }
    //过滤掉v不是2的数据
    for ((k, 2) <- map){
      println(k,2)
    }
    //过滤掉v=2的数据
    for ((k, v) <- map){
      if (v != 2){
        println(k, v)
      }
    }
    //TODO 使用偏函数过滤
    //过滤当v!=2,变成k-0
//    val iterable = map.collect { case (k: String, v: Int) =>{
//      if (v == 2)
//        (k, v)
//      else
//        (k, 0)
//    }}
    //过滤当v=2,变成k-0
    val iterable = map.collect { case (k: String, v: Int) => {
      if (v != 2)
        (k, v)
      else
        (k, 0)
    }}
    println(iterable)
③ 函数参数
    //TODO 功能函数中使用模式匹配
    //将数量都乘以2
    val map = Map((("河北", "鞋子"), 10), (("河南", "衣服"), 26))
    //注意和功能函数一起使用需要将map()改为大括号{},因为编译器以为传了两个参数呢~
    val result: Map[String, (String, Int)] = map.map {
      case ((prv, item), num) => (prv, (item, num * 2))
    }
    println(result)

11.10 偏函数

  • 偏函数就是使用collect{}来对符合条件的数据,进行操作。

    注意需要使用collect方法,使用大括号!!!

  • 大括号内写匹配模式

object Test1_Match_8 {
  def main(args: Array[String]): Unit = {
    //TODO 模式匹配 - 偏函数
    //将List(1, 2, 3, 4, "test", true)这个集合中,Int类型*2,去掉其他类型
    val list = List(1, 2, 3, 4, "test", true)

//    val result = list.map {
//      case i: Int => i * 2
//      case s => s
//    }.filter(_.isInstanceOf[Int])

    //如果不适用模式匹配的话,那么就得这样做,需要isInstanceOf判断类型,然后asInstanceOf转换类型
//    val result = list.map(t => {
//      if (t.isInstanceOf[Int]) {
//        t.asInstanceOf[Int] * 2
//      } else {
//        t
//      }
//    })

    //TODO 采用偏函数
    val result = list.collect { case i: Int => i * 2 }

    println(result)
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

最佳第六六六人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值