欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

scala match

程序员文章站 2022-06-14 17:14:49
...

  • 基础示例

  1. 如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句
  2. 如果所有 case 都不匹配,又没有写 case _ 分支,那么会抛出 MatchError
  3. 每个 case 中,不用 break 语句,自动中断 case
  4. => 后面的代码块到下一个 case, 是作为一个整体执行,可以使用{} 括起来,也可以不括。
package com.xcu.chapter12

object demo01_match {
  def main(args: Array[String]): Unit = {
    val oper = '-'
    val n1 = 20
    val n2 = 10
    var res = 0
    oper match {
      case '+' => res = n1 + n2
      case '-' => res = n1 - n2
      case '*' => res = n1 * n2
      case '/' => res = n1 / n2
      case _ => println("error")
    }
    println(res)  // 10
  }
}
  • 模式匹配也可以有返回值
package com.xcu.chapter12

object demo02_MatchVar {
  def main(args: Array[String]): Unit = {
    val ch1 = '@'
    //match 是一个表达式,因此可以有返回值
    val res = ch1 match {
      case '@' => ch1 + "laowang"
      case _ => println("not match")
    }
    println(res)  // @laowang
  }
}

  • 守卫

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

package com.xcu.chapter12

object demo01_match {
  def main(args: Array[String]): Unit = {
    for (ch <- "+-3ec") { // 是对"+-3!" 遍历
      var dight = 0
      ch match {
        case '+' => println("+")
        case '-' => println("-")
        // 如果 case 后有条件守卫即if ,那么这时的 _ 不是表示默认匹配 是表示忽略传入的ch
        case _ if ch.toString.equals("3") => dight = 3
        case _ if (ch > 99) => {
          printf("%s > 69\n", ch)
        }
        case _ => println("match error!")
      }
    }
  }
}
  • 模式中的变量

如果在 case 关键字后跟变量名,那么 match 前表达式的值会赋给那个变量

package com.xcu.chapter12

object demo02_MatchVar {
  def main(args: Array[String]): Unit = {
    val ch = 'h'
    ch match {
      // 下面 case mychar 含义是 mychar = ch
      case mychar => println(mychar + "ello")
      case _ => println("not match!")
    }
  }
}

  • 匹配类型

可以匹配对象的任意类型,这样做避免了使用 isInstanceOf 和 asInstanceOf 方法

package com.xcu.chapter12

object demo03_Match_Type {
  def main(args: Array[String]): Unit = {
    val a = 4
    //说明 obj 实例的类型 根据 a 的值来返回
    val obj = if (a == 1) 1
    else if (a == 2) "2"
    else if (a == 3) BigInt(3)
    else if (a == 4) Map("aa" -> 1)
    else if (a == 6) Array(1, 2, 3)
    else if (a == 7) Array("aa", 1)
    else if (a == 8) Array("aa")
    //1. 根据 obj 的类型来匹配
    val result = obj match {
      case a: Int => a
      case b: Map[String, Int] => "对象是一个字符串-数字的 Map 集合"
      case d: Array[String] => d // "对象是一个字符串数组"
      case e: Array[Int] => "对象是一个数字数组"
      case f: BigInt => Int.MaxValue
      case _ => "not amtch!"
    }
    println(result)  // 对象是一个字符串-数字的 Map 集合
  }
}
  • 匹配数组
package com.xcu.chapter12

import scala.collection.mutable.ArrayBuffer

object demo04_Match_Arr {
  def main(args: Array[String]): Unit = {
    //给你一个数组集合,如果该数组时 Array(10,20) , 请使用默认匹配,返回 Array(20,10)
    val arrs = Array(Array(1, 1, 0), Array(0, 1), Array(0))

    for (arr <- arrs) {
      val result = arr match {
        case Array(0) => "0"
        case Array(x, y) => ArrayBuffer(y, x)
        case Array(1, _*) => "以1开头和数组"
        case _ => "not match!"
      }
      println(result)
    }
  }
}

输出

1开头和数组
ArrayBuffer(1, 0)
0
  • 匹配列表

package com.xcu.chapter12

object demo05_list {
  def main(args: Array[String]): Unit = {
    for (list <- Array(List(7), List(1, 0), List(88), List(0, 0, 0), List(1, 0, 0))) {
      val result = list match {
        case 7 :: Nil => "7" // 匹配7
        case x :: y :: Nil => y + " " + x // 匹配只有2个元素的列表
        case 0 :: tail => "0 ..." // 匹配0开头的列表
        case x :: Nil => x // 匹配只有1个元素的列表
        case _ => "something else"
      }
      println(result)
    }
  }
}

输出

7
0 1
88
0 ...
something else
  • 匹配元组

package com.xcu.chapter12

object demo06_MatchTuple {
  def main(args: Array[String]): Unit = {
    for (pair <- Array((0, 1), (1, 0), (10, 30), (1, 0, 2))) {
      val result = pair match {
        case (0, _) => "0 ..." // 匹配以0开头的元组
        case (y, 0) => y // 匹配第二个元素为0的元组
        case (x, y) => (y, x) // 匹配到只有2个元素的元组
        case _ => "other"
      }
      println(result)
    }
  }
}
  • 匹配对象

  • 对象匹配,什么才算是匹配呢?规则如下:
  1. case 中对象的 unapply 方法(对象提取器)返回 Some 集合则为匹配成功
  2. 返回 None 集合则为匹配失败
  • 案列1
package com.xcu.chapter12

object demo07_MatchObject {
  def main(args: Array[String]): Unit = {
    // 模式匹配使用:
    val number: Double = Square(6) // 36.0 //
    number match {
      //1. 当匹配到 case Square(n)
      //2. 调用 object Square 的 unapply(z: Double),z 的值就是 number
      //3. 如果对象提取器 unapply(z: Double) 返回的是 Some(6) ,则表示匹配成功,同时将6赋给 Square(n)的n
      //4. 如果对象提取器 unapply(z: Double) 返回的是 None ,则表示匹配不成功
      case Square(n) => println("匹配成功 n=" + n)
      case _ => println("not match")
    }
  }
}

object Square {
  //1. unapply 方法是对象提取器
  //2. 接收 z:Double 类型
  //3. 返回类型是 Option[Double]
  //4. 返回的值是 Some(math.sqrt(z))即z的开平方的值,并放入到 Some(x)
  def unapply(z: Double): Option[Double] = {
    Some(math.sqrt(z))
    None
  }

  def apply(z: Double): Double = z * z
}
  • 案列2
package com.xcu.chapter12

object demo07_MatchObject {
  def main(args: Array[String]): Unit = {
    val wordString = "Alice,Bob,Thomas" //字符串
    //说明
    wordString match {
      /* 当执行到 case Split_word(first, second, third)时
       1.会调用 unapplySeq(str),把 "Alice,Bob,Thomas" 传入给unapplySeq的 str
       2.如果unapplySeq返回的是 Some("Alice","Bob","Thomas"),
          分别给 Split_word(first, second, third)
          注意 这里的unapplySeq返回的值的个数需要和 Split_word(first, second, third)要一样
       3.如果unapplySeq返回的 None ,表示匹配失败*/
      case Split_word(first, second, third) => {
        println(s"$first $second $third")
      }
      case _ => println("nothing matched")
    }
  }
}

object Split_word {
  //当构造器是多个参数时,就会触发这个对象提取器
  def unapplySeq(str: String): Option[Seq[String]] = {
    if (str.contains(",")) 
      Some(str.split(","))
    else 
      None
  }
}
相关标签: scala