二. 模式匹配

一. 更好的switch:match

  1. match匹配任何类型
    scala> var ch = '*'
    ch: Char = *
    
    scala> var sign=""
    sign: String = ""
    
    scala> ch match{  // match表达式         
         |     case '+' => sign="1"
         |     case '-' => sign="-1"
         |     case _ => sign="not in +/-"
         | }
    
    scala> print(sign)
    not in +/-
    

【注】:
(1)与java不同,match中的每个case语句,不需要显示的声明break,不用担心“跳入下一个分支”
(2)如果未声明case _ 来匹配任一选项,则会抛出MatchError异常
(3) 与if类似,match是表达式,而非语句

  1. 带守卫的match
    守卫是一个boolean类型的条件,用来给case _加限定条件

    scala> ch match {
         |     case '+' => sign="0"
         |     case _ if Character.isDigit(ch) => sign="is digit"  // 守卫
         |     case _ => sign="orthers"
         | }
    
    scala> print(sign)
    is digit
    
  2. case的常量匹配
    case可用常量匹配,scala识别常量的方法是:以大写字母开头的名字认为是常量。所以,如果匹配小写字母开头的常量,需要将常量用反引号扩起来

    scala> val ADD = "+"
    ADD: String = +
    
    scala> var ch = "+"
    ch: String = +
    
    scala> ch match {
         |     case ADD => print("111")    // 大写开头的ADD,scala自动识别为常量匹配
         |     case "-" => print("222")
         | }
    111
    
    scala> val add="+"
    scala> ch match {
         |     case `add` => print("111")   // 小写字母开头的常量反引号引起来:`add`
         |     case "-" => print("222")
         | }
    111
    
    
  3. 变量数值类型的匹配
    (1)scala用match匹配变量的参数类型,而不去时用isInstanceOf操作符
    (2)如果match返回的结果依赖于需要匹配的变量值,则case语句后面加上别名
    (3)类型匹配不能去匹配集合泛型,因为泛型是编译时期约束,而match是运行时代码

    var obj:Any = "11"    
    val result = obj match{
        case x: Int => 2 * x
        case s: String => Integer.parseInt(s)+"aaa"
        case _ => 0
    }
    println(obj)    //11
    println(result) //11aaa
    
    
    var obj2:Any="11"
    val result2 = obj2 match {
      case _ : Int => 111       // result2的表达式用不上obj2,不用起别名
      case _ => 0
    }
    println(result2)
    
  4. 数组,List, 元组的模式匹配
    (1)数组:数组的匹配项可以匹配任意长度的Array
    (2)List:list时固定长度的列表,list分为head和tail2部门,head时list的第一个元素,tail是list中除了head外的其余元素组成的list。用::连接list时,尾节点要声明成Nil
    (3)元组:元组的匹配项,要与原元组用相同的元素个数,元素类型

    //1. Array匹配
    var arr = Array(1,2,3)
    val s: String = arr match {
      case Array(0) => "0"
      case Array(x,y) => "2 param array"
      case Array(1, _*) => "1 ..."
      case _ => "anything else"
    }
    print(s)
    
    //2. List匹配
    var digitList = List(1,2,4)
    var list2 = 9 :: List(4,2) :: 2 :: Nil  //list
    
    val value: Any = list2 match {
      case 9 :: Nil => 9
      case x :: y :: Nil => x + "" + y
      case _ => "something else"
    }
    print(value)   //something else
    
    //3. 元组匹配
    var tuple1 = (1,"abc",'d')
    tuple1 match {
      case (0,"asd", _) => "haha"
      case (x,y,'d') => "d"
      case _ => "anything"
    }
    

三. 其他模式

  1. 集合声明中的模式
    (1)元组声明中的变量匹配

    val (x,y) = (1,2)
    print(x)   //1
    

(2)数组声明中的变量匹配
scala val arr = Array(1,2,3) var Array(first,scend,3) = arr print(first) //1

  1. for推导式的模式匹配
    import scala.collection.JavaConversions.propertiesAsScalaMap     //将java的properties转换成scala的映射
    
    for((k,v) <- System.getProperties){
      print(k+"==>"+v)
    }
    
    for((k,"") <- System.getProperties){
      println(k)
    }
    // 带守卫的for
    for((k,v) <- System.getProperties if v==""){
      println(k)
    }
    

四. 样例类

  1. case类与普通类的区别
    (1)构造器的每一个参数都默认为val的,除非它被显式地声明成var
    (2)case类的伴生对象自动加上apply方法,使得不用new关键字就能构造处对象
    (3)自动生成unapply()方法供提取器模式匹配
    (4)自动产生toString,equals,hashCode,copy方法。其他特性和普通类相同,如继承等

    abstract class Amount
    
    case class Dollar(value:Double) extends Amount                   //样例类
    case class Currency(value:Double,unit:String) extends Amount
    case object Nothing extends Amount                               //样例对象
    
    //样例类模式匹配
    val amt:Any = Currency(11.2,"asd")
    val s: String = amt match {
      case Dollar(v) => "$" + v
      case Currency(_, v) => "i got " + v
      case Nothing => ""
    }
    s //i got asd
    
    class A(value:String){}
    var aa = new A("111")  //普通类不会自动加上apply()
    
  2. copy方法和带名参数
    copy()方法创建了一个与对象值相同的新对象,可以制定参数值类构建新对象

    val amt2 = Currency(29.95,"EUR")
    val price = amt2.copy()              //price: Currency = Currency(29.95,EUR)
    val price2 = amt2.copy(value=11.2)   //price2: Currency = Currency(11.2,EUR)
    val price3 = amt2.copy(unit="CHF")   //price3: Currency = Currency(29.95,CHF)
    

五. Option类型

  1. Option类是一个样例类,常用于表示函数的返回值类型:Option[T]。表示那种可能存在,也可能不存在的值。
  2. 存在的值用子类Some包装。eg:Some("Fred"),表示返回fred字符串
  3. 不存在的值用None表示
    object Test extends App{
    
      private val map: Map[String, Int] = Map(("fred",1),("lucy",2))
      map.get("fred") match { // map的get方法返回Option类型,模式匹配用Some或none匹配
        case Some(1) => println(1)
        case None => println("no value")
      }
      
      //getOrElse方法利用上面的模式匹配
      map.getOrElse("zhangsan",{println("no value")})     //no value
    }
    
    

六. 偏函数

  1. 偏函数:没有定义所有情况的case语句块
  2. 偏函数常用于参数传入
    object TestLazyView extends App{
      val res = "-3+4".collect({case '-' => 1;case '+' => -1})   //Vector(1, -1)
      println(res)
    }
    
    
原文地址:https://www.cnblogs.com/72808ljup/p/5409033.html