Scala之模式匹配

目录

一、基本语法

二、模式守卫

三、匹配类型

四、偏函数模式匹配

一、基本语法

        模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case _分支。

// 模式匹配的基础语法
    val a:Int = 10
    val b:Int = 20
    var c:Char = '+'

    // 通过模式匹配  判断c的值 进行ab直接的运行
    // 基础的语法: 采用match关键字进行匹配  采用case来写匹配的值
    // 匹配到之后执行相关的代码  不需要写break  也不需要写{}  自动根据下一个case来截断
    // 如果匹配不到对应的值  会报错 scala.MatchError   所以需要添加匹配不到的默认情况_
    c match {
      case '+' =>
        println("hi")
        println(a + b)
      case '-' => println(a - b)
      case '*' => println(a * b)
      case '/' => println(a / b)
      case _ => println("运算符错误")
    }

二、模式守卫

        如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。

    // 匹配守卫
    // 返回整数的绝对值
    def func1(x:Int):Int = {
      // 模式匹配具有返回值
      // 返回值是所有条件分支的共同结果  如果类型不一样  使用共同的父类
      val i1: Int = x match {
        case i: Int if i > 0 => x
        case i: Int if i <= 0 => -x
        case  _ => 0
      }
      i1
    }

三、匹配类型

1.匹配常量

 // 匹配常量
    def func1(x: Any): String = {
      x match {
        case 10 => "整数"
        case 3.1 => "小数"
        case "hello" => "字符串"
        case 'c' => "字符"
        case _ => "其他数据"
      }
    }

2.匹配类型

    // 匹配类型
    def func2(x: Any): String = {
      x match {
        case i: Int => "整数" + i
        case i: String => "字符串"
        case i: Char => "字符"
        case i: Double => "小数"
        case _ => "其他类型"
      }
    // 底层实现
      //      if (x.isInstanceOf[Int]) {
      //        "整数"
      //      }else if (x.isInstanceOf[String]){
      //        "字符串"
      //      }else{
      //        "其他类型"
      //      }

3.匹配数组

 // [_ >: Int] 泛型下限  任何比Int大的类型
    val arrays: Array[Array[_ >: Int]] = Array(Array(0),
      Array(1, 0), Array(0, 1, 0), Array(1, 1, 0), Array(1, 1, 0, 1), Array("hello", 90))

    for (array <- arrays) {
      array match {
        case Array(0) => println("只有一个元素0的数组")
        case Array(1,x) => println(s"有两个元素  并且第一个为1 第二个为$x")
        case Array(_,_,_) => println("有三个元素的数组")
        case Array(_*) => println("其他数据")
      }
    }

4.匹配列表

  def func1(x:Any):String = {
      x match {
        case a:Array[Int] => "整数类型的数组"
        case a:Array[Double] => "小数类型的数组"
        case a:Array[Char] => "字符类型的数组"
        case a:Array[String] => "字符串类型的数组"
        case _ => "其他类型"
      }
    }

    // 数组可以准确匹配其中的泛型
    println(func1(Array(1, 2, 3, 4)))
    println(func1(Array('c','a')))
    println(func1(Array("s","a")))
    println(func1(Array(1.0, 2.1, 2.3, 3.4)))
    println(func1(Array(true,false)))


    // 匹配集合的泛型
    // 存在泛型擦除问题
    // 在进行类型判断的时候  只能判断他是一个集合  不是判断集合的泛型
    def func2(x:Any):String = {
      x match {
        case a:List[Double] => "小数类型的集合"
        case a:List[Int] => "整数类型的集合"
        case a:List[Char] => "字符类型的集合"
        case a:List[String] => "字符串类型的结合"
        case _ => "其他类型"
      }
    }

    println("===============")
    println(func2(List(1, 2, 3, 4)))
    println(func2(List('c','a')))
    println(func2(List("s","a")))
    println(func2(List(1.0, 2.1, 2.3, 3.4)))
    println(func2(List(true,false)))

  }

5.匹配元组

def main(args: Array[String]): Unit = {
        //对一个元组集合进行遍历
        for (tuple <- Array((0, 1), (1, 0), (1, 1), (1, 0, 2))) {

            val result = tuple match {
                case (0, _) => "0 ..." //是第一个元素是0的元组
                case (y, 0) => "" + y + "0" // 匹配后一个元素是0的对偶元组
                case (a, b) => "" + a + " " + b
                case _ => "something else" //默认
            }
            println(result)
        }
    }

6.匹配对象

  def main(args: Array[String]): Unit = {
    val person0 = new Person05("zhangsan", 10)
    val person01: Person05 = Person05("zhangsan", 10)
//语句在执行时,实际调用的是Person05伴生对象中的apply方法,因此不用new关键字就能构造出相应的对象
    val ints: Array[Int] = Array(0)

    // 需要两个方法才能完成匹配对象
    // 1. apply方法  在模式匹配中直接创建对象
    // 2. unapply方法  解析方法  解析对象中的属性  判断属性是否相同完成模式匹配
    person0 match {
      case Person05("zhangsan",10) => println("找到张三了")
    }

  }
}

//class Person05 (val name:String,var age:Int){}
//
//object Person05{
//  // 需要使用apply方法创建对象
//  def apply(name: String, age: Int): Person05 = new Person05(name, age)
//
//  // 需要使用unapply方法解析对象
//  def unapply(arg: Person05): Option[(String, Int)] = {
//    // 需要自己实现解析
//    // 如果对象不为空  将他的属性封住进option中返回  如果为空 返回none
//    if (arg == null){
//      None
//    }else {
//      Some((arg.name,arg.age))
//    }
//case中对象的unapply方法(提取器)返回Some,且所有属性均一致,才算匹配成功,属性不一致,或返回None,则匹配失败
//若只提取对象的一个属性,则提取器为unapply(obj:Obj):Option[T]
//若提取对象的多个属性,则提取器为unapply(obj:Obj):Option[(T1,T2,T3…)]
//若提取对象的可变个属性,则提取器为unapplySeq(obj:Obj):Option[Seq[T]]
//  }
//}

// 使用样例类
// 样例类会自动帮你实现apply和unapply方法
case class Person05(name:String,var age:Int){}

样例类:

1.样例类仍然是类,和普通类相比,只是其自动生成了伴生对象,并且伴生对象中自动提供了一些常用的方法,如apply、unapply、toString、equals、hashCode和copy。

2.样例类是为模式匹配而优化的类,因为其默认提供了unapply方法,因此,样例类可以直接使用模式匹配,而无需自己实现unapply方法。

3.构造器中的每一个参数都成为val,除非它被显式地声明为var

四、偏函数模式匹配

定义:函数的一种,方便的对输入参数做更精确的检查

val second: PartialFunction[List[Int], Option[Int]] = {
    case x :: y :: _ => Some(y)
}

        与普通函数相比,只是多了一个用于参数检查的函数——isDefinedAt,其返回值类型为Boolean。 

        偏函数不能像second(List(1,2,3))这样直接使用,因为这样会直接调用apply方法,而应该调用applyOrElse方法,如下

        second.applyOrElse(List(1,2,3), (_: List[Int]) => None)

        applyOrElse方法的逻辑为 if (ifDefinedAt(list)) apply(list) else default。如果输入参数满足条件,即isDefinedAt返回true,则执行apply方法,否则执行defalut方法,default方法为参数不满足要求的处理逻辑。

 def main(args: Array[String]): Unit = {

    val list = List(1, 2, 3, 4, 5)

    // 输出集合的第二个参数
    val i: Int = list match {
      case List(_, x, _*) => x
      case _ => 0
    }
    println(i)

    // 创建一个偏函数
    // 带有两个方法  一个相当于过滤  一个相当于转换
    val value: PartialFunction[List[Int], Int] = new PartialFunction[List[Int], Int] {
      // 当前偏函数在什么时候进行匹配
      // 如果不匹配会将元素扔掉
      override def isDefinedAt(x: List[Int]) = {
        x match {
          case List(_, x, _*) => true
          case _ => false
        }
      }

      // 匹配的逻辑
      override def apply(v1: List[Int]) = {
        list match {
          case List(_, x, _*) => x
        }
      }
    }

    // 将模式匹配写成匿名函数
    val function: List[Int] => Int = (x: List[Int]) => x match {
      case List(_, x, _*) => x
      case _ => 0
    }

    // 偏函数的写法 其实就是省略掉match
    val function1: PartialFunction[List[Int], Int] = {
      case List(_, x, _*) => x
      case _ => 0
    }


    //    将该List(1,2,3,4,5,6,"test")中的Int类型的元素加一,并去掉字符串

    val list1: List[Any] = List(1, 2, 3, 4, 5, 6, "test")

    // 如果不使用偏函数
    val list2: List[Any] = list1.filter((x: Any) => x match {
      case s: String => false
      case _ => true
    })

    println(list2)

    val list3: List[Int] = list2.map((x: Any) => x match {
      case i: Int => i + 1
    })

    println(list3)

    // 使用偏函数
    // map 必须填写一个1对1的函数  不能使用偏函数
    // 特定的函数才是支持偏函数的  比如collect 能够实现偏函数 过滤加转换的功能

    // 后续的使用  不会用到偏函数底层的原理  过滤加转换   只是单纯的将写法简化 -> 省略掉match
    val list4: List[Int] = list1.collect({
      case i: Int => i + 1
    })
    println(list4)
  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值