scala--模式匹配-★★★

Java中的switch-case–了解即可-★

  • 只能按顺序匹配简单的数据类型和表达式(支持:byte、short、int、char、String、枚举,不支持long)
  • 相对而言,Scala中的模式匹配math-case的功能则要强大得多,几乎可以在match中使用任何类型、应用到更多场合
  • 并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配。
package cn.hanjiaxiaozhi.casedemo;

/**
 * Author hanjiaxiaozhi
 * Date 2020/7/17 11:30
 * Desc 演示java中的switch
 */
public class Case_Java {
    
    
    public static void main(String[] args) {
    
    
        //需求:根据数字打印是工作日还是休息日
        int day = 6;
        if(day <=1 && day <=5){
    
    
            System.out.println("今天是工作日");
        }else{
    
    
            System.out.println("今天是周末~休息");
        }

        //当条件很多的时候可以改造成switch
        switch (day){
    
    
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                System.out.println("今天是工作日");
                break;
            default:
                System.out.println("今天是周末~休息");
        }

        //Java之后的switch~case可以完成类似于if-else的条件判断
        //但是有限制:switch (参数),只支持:byte,short,int,String,枚举,不支持其他的复杂类型,甚至是Long
        //而Scala中的模式匹配很强大,支持一切~
        //当然Java后续的新版本也开始慢慢学习Scala
    }
}

Scala中的模式匹配-★★★

  • 注意:
    • case语句中不需要使用break语句
    • case_ 相当于Java中的default
  • 只需要掌握前3个,其他的了解
package cn.hanjiaxiaozhi.casedemo

import scala.util.Random

/**
 * Author hanjiaxiaozhi
 * Date 2020/7/17 11:38
 * Desc 演示Scala中的模式匹配--类似Java中的switch-case,但是比Java的要强大
 */
object Case_Scala {
    
    
  def main(args: Array[String]): Unit = {
    
    
    //1.匹配字符串/数字...--掌握
    println("===============匹配字符串/数字=============")
    val arr1 = Array("hadoop", "zookeeper", "spark", "flink")
    val index: Int = Random.nextInt(arr1.length) //获取[0~arr1.length)的随机数
    val str: String = arr1(index)
    println(str)
    str match {
    
    
      case "hadoop" => println("大数据存储计算框架")
      case "zookeeper" => println("分布式协调服务框架")
      case _ => println("大数据计算框架") //相当于default
    }

    //2.匹配类型--掌握
    println("===============匹配类型=============")
    //Array(字符串, Int, Double, object)
    val arr2 = Array("hello", 1, 2.0, Case_Scala)
    val value = arr2(Random.nextInt(4))
    println(value)
    value match {
    
    
      case s: String => println("匹配上String:" + s)
      case i: Int => println("匹配上Int:" + i)
      case d: Double if (d > 0) => println("匹配上大于0的Double:" + d) //可以混合匹配多个条件
      case o: Case_Scala.type => println("匹配上了Case_Scala-object:" + o)
      case _ => println("其他")
    }


    //3.匹配集合(可以一次匹配单个变量,还支持各种符号)--掌握,符号不用记
    println("===============匹配集合=============")
    val arr3 = Array(0, 3, 5)
    arr3 match {
    
    
      case Array(0, x, y) => println(x + " " + y) //可以匹配上
      case Array(0) => println("only 0")
      case Array(0, _*) => println("0 ...") //_*表示后面任意,前面已经匹配上了那么这里就不执行了
      case _ => println("something else")
    }

    val li = List(3, -1)
    li match {
    
    
      case 0 :: Nil => println("only 0")
      case x :: y :: Nil => println(s"x: $x y: $y") //x: 3 y: -1
      case 0 :: tail => println("0 ...")
      case _ => println("something else")
    }

    val tup = (1, 3, 7)
    tup match {
    
    
      case (1, x, y) => println(s"1, $x , $y") //1, 3 , 7
      case (_, z, 5) => println(z)
      case _ => println("else")
    }

    //4.变量声明中隐藏的模式匹配---了解
    println("***变量声明中隐藏的模式匹配***")
    val (x, y) = (1, 2) //表示x = 1,y=2
    println(x) //1
    println(y) //2
    val (q, r) = BigInt(10) /% 3 //10先除以3结果3给q, 10模3结果1给r
    println(q) //3
    println(r) //1
    val arr4 = Array(1, 7, 2, 9)
    val Array(first, second, _*) = arr4 //表示不arr4中的第一个元素给first,第二个元素给second
    println(first, second) //(1,7)


    //5.其他语法中混合使用模式匹配--了解
    println("***其他语法中混合使用模式匹配***")
    val kvs = Map("k1" -> "v1", "k2" -> "v2", "k3" -> "v3")
    for ((k, v) <- kvs) {
    
     //也是模式匹配,只不过不是显式的match-case
      println(k + ":" + v)
    }

    //6.函数式操作中的模式匹配--了解
    println("***6.函数式操作中的模式匹配***")
    kvs.foreach {
    
    
      case (k, v) => println(k, v)
    }


    //7.匹配样例类==后面案例的时候单独使用讲解--先了解
    println("***7.匹配样例类***")
    val arr = Array(CheckTimeOutTask, HeartBeat(10), SubmitTask("001", "task-001"), StopTask)
    val obj =arr(Random.nextInt(arr.length))
    println(obj)
    obj match {
    
    
      case SubmitTask(id, name) => println(s"$id, $name")
      case HeartBeat(time) => println(time)
      case CheckTimeOutTask =>println("check")
      case StopTask => println("stop")
    }

  }
}
case class SubmitTask(id: String, name: String) //样例类--可以根据他创建对象 如: SubmitTask(1, "task1")
case class HeartBeat(time: Long) //样例类
case object CheckTimeOutTask //样例对象,就是一个对象,没有属性 --了解
case object StopTask //样例对象,就是一个对象,没有属性--了解

补充:Option类型

  • 在Scala中为单个值提供了对象的包装器,Option类型用样例类来表示可能存在或也可能不存在的值
  • Option的子类有Some和None,Some包装了某个值,None表示没有值
  • 通过Option的使用,避免了使用null、空字符串等方式来表示缺少某个值的做法
package cn.hanjiaxiaozhi.case_demo

object OptionDemo {
    
    
  def main(args: Array[String]) {
    
    
    val map = Map("a" -> 1, "b" -> 2)

    //使用模式匹配:从map中根据k获取v,如果获取到了直接返回,没获取到返回默认值0
    val v = map.get("c") match {
    
    
      //Option是一个装有1个或0个元素的容器
      //Some和None都是Option的子类
      case Some(i) => i //Some里面有1个元素
      case None => 0 //None里面有0个元素
    }
    println(v)

    //使用getOrElse
    val v2: Int = map.getOrElse("a",0)
    println(v2)
  }
}

补充:异常处理

  • 说明
    • 受检异常在编译期被检查,在Java中必须在方法上声明该方法可能会发生的受检异常
    • Scala的异常的工作机制和Java一样,但是Scala没有checked受检异常,你不需要声明函数或者方法可能会抛出某种异常。
  • 抛出异常:
    • 用throw关键字,抛出一个异常对象。所有异常都是Throwable的子类型。
    • throw表达式是有类型的,就是Nothing,因为Nothing是所有类型的子类型,所以throw表达式可以用在需要类型的地方。
  • 捕捉异常:
    • 在catch的代码里,使用一系列case子句(借用了模式匹配的思想来做异常的匹配)
    • 异常捕捉的机制与其他语言中一样,如果有异常发生,catch字句是按次序捕捉的。因此,在catch字句中,越具体的异常越要靠前,越普遍的异常越靠后。
    • 如果抛出的异常不在catch字句中,该异常则无法处理,会被升级到调用者处。
    • finally字句用于执行不管是正常处理还是有异常发生时都需要执行的步骤,一般用于对象的清理工作。
package cn.hanjiaxiaozhi.case_demo

object ExceptionDemo {
    
    
  def main(args: Array[String]): Unit = {
    
    
    try {
    
    
      println(divider(10, 0))
    } catch {
    
    
      case ex: Exception => println("捕获了异常:" + ex)
    } finally {
    
    
      println("释放资源")
    }
    println("处理了异常,代码继续往下执行")
  }

  def divider(x: Int, y: Int): Float = {
    
    
    if (y == 0) throw new Exception("0作为了除数")
    else x / y
  }
}

扩展:偏函数

  • 被包在花括号内没有match的一组case语句是一个偏函数
  • 偏函数是PartialFunction[A, B]的一个实例,A代表参数类型,B代表返回类型,常用作输入模式匹配
  • 偏函数最大的特点就是它只接受和处理其参数定义域的一个子集
package cn.hanjiaxiaozhi.case_demo

object PartialFuncDemo {
    
    
  //方法
  def func1(num: String): Int ={
    
    
    num match {
    
    
      case "one" => 1
      case "two" => 2
      case _ => -1
    }
  }
  //偏函数
  val func2: PartialFunction[String, Int] = {
    
    
    case "one" => 1
    case "two" => 2
    case _ => -1
  }

  def main(args: Array[String]) {
    
    
    //1.调用方法
    println(func1("one"))

    //2.调用偏函数
    println(func2("one"))

    val list = List(1,6,8)
    //3.传入偏函数
    val list2 = list.map{
    
    
      case x if x >= 1 && x <= 5 => "工作日"
      case x if x >= 6 && x <= 7 => "休息日"
      case x if x > 7 => "不认识"
    }
    println(list2)
  }
}

扩展:提取器

  • 之前我们学习过了,实现一个类的伴生对象中的apply方法,可以用类名来快速构建一个对象
  • 伴生对象中,还有一个unapply方法。与apply相反,unapply是将该类的对象,拆解为一个个的元素,常用于模式匹配
  • 样例类中自动提供apply方法和unapply方法
    在这里插入图片描述
class Student(var name: String, var age: Int)

object Student {
    
    
  def apply(name: String, age: Int) = {
    
    
    println("apply方法被调用")
    new Student(name, age)
  }

  def unapply(s: Student) = {
    
    
    println("unapply方法被调用")
    if(s != null ) {
    
    
      Some(s.name, s.age)
    }
    else {
    
    
      None
    }
  }
}

object TestStudent {
    
    
  def main(args: Array[String]): Unit = {
    
    
    //调用apply
    val s = Student("张三", 20)

    //调用unapply
    s match {
    
    
      case Student(name, age) => println(s"${name} => ${age}")
    }
  }
}

猜你喜欢

转载自blog.csdn.net/qq_46893497/article/details/114043633