scala 系列之 11scala 模式匹配

教程 潘牛 ⋅ 于 2021-07-08 22:50:50 ⋅ 1225 阅读

14 模式匹配

14.1 match 语句

match 语句用在当需要从多个分支中进行选择的场景,类似于java 中的switch 语句。

语法:

变量 match{
    case "值"  => 语句块1  // 语句块后不用加break
    case "值2" => 语句块2
    case _ => 语句块N    // 类似于java的default
}

其中:

1)case 后面的表达式可以是任何类型的常量,如字段串、类、元组、集合等;

2)与java的switch不同的是,match 结构中不需要break 语句来跳出判断;

3)最后一个case语句用了通配符“_”,相当于java的default;

4)如果匹配不到,就会报错;

14.2 字符串匹配

import scala.util.Random
object MatchDemo {
  def main(args: Array[String]): Unit = {
    var arr = Array("A","B","C","D")
    val a = arr(Random.nextInt(arr.length))
    println(a)
    a match {
        case "A" => println("a")
        case "B" => println("b")
        case "C" => println("c")
        case _ => println("other")
    }
  }
}

14.3 类型匹配

​ match除了匹配特定的常量,还能匹配某种类型的所有值;

​ 在scala 中倾向于用这样的模式匹配,而不是isInstanceOf 操作符;

package day03
import scala.util.Random
object MatchDemo2 {
  def main(args: Array[String]): Unit = {
    val arr: Array[Any] = Array(1, 100L, 3.14, "1000", Array[Int](1,2,3))
    val data: Any = arr(Random.nextInt(arr.size))
    var data2:Int = 0
    // 用 match匹配类型
    data match {
      case x:Int => data2 = x
      case x:Long => data2 = x.toInt
      case x:Double => data2 = x.toInt
      case x:String => data2 = x.toInt
      case x:Array[Int] => data2 = x.sum
    }
    println(s"data:${data}, data2:${data2}")
    // 这种多类型匹配不适合用 isInstanceOf, asInstanceOf
//    if(data.isInstanceOf[Int]){
//      data2 = data.asInstanceOf[Int]
//    }else if(data.isInstanceOf[Long]){
//      data2 = data.asInstanceOf[Long].toInt
//    }
  }
}

14.4 数组、元组、集合匹配

元组匹配时case后面的值的个数应与被匹配的元组中数据的个数相同,否则报错。

当有多个条件能匹配到时以最先匹配到的条件为准

object MatchDemo3 {
  def main(args: Array[String]): Unit = {
    val arr = Array(1, 2, 3, 4)
    arr match {
      case Array(1, x, y) => println(s"x:$x,y:$y")
      case Array(_, x, y, d) => println(s"x:$x,y:$y,d:$d")
      case _ => println("other")
    }
    val tuple = (5, 6, 7)
    tuple match {
      case (1, a, b) => println(s"case1 a:$a,b:$b")
      case (3, a, b) => println(s"case2 a:$a,b:$b")
      case (_, x, y) => println(s"case3 a:$x,b:$y")
      case _ => println("other")
    }
    val list = List(7,8,9)
    list match {
      case 7 :: b :: Nil => println(s"case 1 b:$b")
      case List(a,b,c) => println(s"case 2 a:$a,b:$b,c:$c")
      case 7 :: 8 :: b :: Nil => println(s"case 3 b:$b")
      case _ => println("other")
    }
  }
}
//-----------运行结果-----------------
x:2,y:3,d:4
case3 a:6,b:7
case 2 a:7,b:8,c:9

14.5 偏函数匹配

1)使用 case 语句构造匿名函数与偏函数。

// 构造匿名函数
val list = List(1,2,3)
// 下面三种方式同等效果
val list1 = list.map((x:Int) => x*2)    
// 编译器把case语句翻译成普通函数
val list2 = list.map({case x:Int => x*2})
val list3 = list map {case x:Int => x*2}  
// 当把case语句翻译成普通函数时,如果匹配不上会报错
val list4 = List(1,2,3,"aaa",4)
//这句就会报错
val list5 = list4 map {case x:Int => x * 2}
val list = List(1,2,3, "aaa", 4)
// collect 接收偏函数作为参数,此时把case语句作为参数传递,scala编译器会把 case 语句翻译成偏函数
// 当构造偏函数时,值匹配能匹配上的,不能匹配上的放弃并顾虑掉;
list.collect({case x:Int => x*2})
res10: List[Int] = List(2, 4, 6, 8)

总结:

当编译器把case语句翻译成函数时,如果匹配不上会报错;

当编译器把case语句翻译成偏函数时,匹配不上的放弃并过滤掉;

2)偏函数

在Scala中,所有偏函数的类型皆被定义为 PartialFunction[-A, +B] 类型,PartialFunction[-A, +B] 又派生自 Function1 。

PartialFunction[-A, +B] ,其中 A 是方法参数类型,B是方法返回值类型。

PartialFunction(偏函数)内部常与 case 语句搭配,进行模式匹配,函数体里的模式匹配没有match关键字;

当把偏函数作为函数使用时,如果匹配不上会报错;

当把偏函数作为偏函数时,匹配不上的放弃并过滤掉;

package day03
object MatchDemo3 {
  // 定义普通方法
  def m1(data:Any):Int = {
    data match {
      case x:Int => x * 10
//      case x:String => x.toInt * 10
//      case _ => 0
    }
  }
  // 定义偏函数
  def func:PartialFunction[Any, Int] = {
    case x:Int => x * 10
  }
  def main(args: Array[String]): Unit = {
    println(m1(10))
    //println(m1("10"))
    println(func(10))
    val list = List(1,2,3, "aa", "bb")
    // collect接收偏函数,func定义时只要Int
    println(list.collect(func))
    println(list.map(m1))
  }
}

file

版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-潘牛,http://hainiubl.com/topics/75746
成为第一个点赞的人吧 :bowtie:
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter