scala 模式匹配概念及用法示例

scala 模式匹配

Scala 中的模式匹配是一种强大的语言特性,它可以用来匹配和提取各种数据结构中的元素,包括元组、列表、类和 case 类等

模式匹配的基本语法是使用 match 关键字和一系列的 case 分支。例如,下面的示例代码展示了如何匹配一个整数并输出相应的字符串:

val x = 1
val result = x match {
  case 1 => "one"
  case 2 => "two"
  case _ => "other"
}
println(result) // 输出 "one"

在上面的代码中,模式匹配使用了 match 关键字和三个 case 分支。当 x 的值为 1 时,它会匹配第一个分支并返回字符串 “one”。如果 x 的值为 2,它会匹配第二个分支并返回字符串 “two”。如果 x 的值不是 1 或 2,它会匹配最后一个分支并返回字符串 “other”。

除了基本类型的匹配,模式匹配还可以用于提取元组和列表中的元素。例如,下面的代码展示了如何从一个元组中提取第一个和第二个元素:

val tuple = (1, "two")
val (a, b) = tuple
println(a) // 输出 1
println(b) // 输出 "two"

类和 case 类的匹配也是模式匹配的重要应用。例如,下面的代码展示了如何匹配一个简单的类:

class Person(val name: String, val age: Int)

val person = new Person("Alice", 30)
person match {
  case p: Person => println(s"Name: ${p.name}, Age: ${p.age}")
  case _ => println("Unknown")
}

在上面的代码中,首先定义了一个 Person 类和一个 person 实例。然后使用模式匹配来检查 person 是否是 Person 类型的实例,并输出相应的信息。

总之,Scala 中的模式匹配是一种强大的语言特性,可以用于匹配和提取各种数据结构中的元素,包括元组、列表、类和 case 类等。

与java对比呢

与 Java 相比,Scala 的模式匹配更灵活、更强大。在 Java 中,通常需要使用 if-else 或者 switch-case 语句来实现类似的功能,而在 Scala 中,模式匹配可以更直接、更简洁地实现这些功能。

例如,在 Java 中,要实现一个类似于 Scala 中的模式匹配的功能,需要使用 switch-case 语句,而且只能匹配基本类型或枚举类型:

int x = 1;
String result;
switch (x) {
  case 1:
    result = "one";
    break;
  case 2:
    result = "two";
    break;
  default:
    result = "other";
    break;
}
System.out.println(result);

而在 Scala 中,可以直接使用模式匹配来实现同样的功能,而且可以匹配更复杂的数据类型:

val x = 1
val result = x match {
  case 1 => "one"
  case 2 => "two"
  case _ => "other"
}
println(result)

此外,Scala 的模式匹配还支持更多的模式匹配方式,例如可以使用 case class 来匹配类的属性,可以使用匹配列表、数组等数据结构,可以使用模式守卫来增加更多的条件判断等等,这些都是 Java 中没有的特性。

总之,与 Java 相比,Scala 的模式匹配更灵活、更强大,可以更直接、更简洁地实现复杂的逻辑。

与python对比呢

与 Python 相比,Scala 的模式匹配更加严格和类型安全。在 Python 中,可以使用 if-elif-else 或者字典等方式来实现类似的功能,而且在匹配时不需要考虑变量的类型,这样虽然在某些情况下可以简化代码,但也会增加代码的不确定性和出错的可能性。

例如,下面是使用 if-elif-else 来实现类似于 Scala 中模式匹配的功能的 Python 代码:

x = 1
if x == 1:
    result = "one"
elif x == 2:
    result = "two"
else:
    result = "other"
print(result)

而在 Scala 中,模式匹配可以更直接、更简洁地实现同样的功能,而且可以保证类型的匹配和类型安全:

val x = 1
val result = x match {
  case 1 => "one"
  case 2 => "two"
  case _ => "other"
}
println(result)

此外,在 Python 中,字典的键可以是任意类型,而值也可以是任意类型,这样虽然增加了灵活性,但也会增加代码的不确定性和出错的可能性。而在 Scala 中,模式匹配的分支必须是类型匹配的,这样可以保证代码的类型安全性。

总之,与 Python 相比,Scala 的模式匹配更加严格和类型安全,可以更直接、更简洁地实现复杂的逻辑,并且可以保证代码的类型安全性。

spark代码哪里用到了模式匹配

在 Spark 中,模式匹配是一种非常常见的编程技巧,被广泛应用在 Spark 的核心代码中,特别是在 RDD、DataFrame 和 Dataset 等数据结构的实现中。

下面是一个使用模式匹配实现 RDD 的 flatMap 操作的例子。在 RDD 的 flatMap 操作中,我们需要将每个输入元素映射为零个或多个输出元素,这个操作可以通过模式匹配来实现:

class RDD[T] {
  def flatMap[U](f: T => TraversableOnce[U]): RDD[U] = {
    new MapPartitionsRDD[U, T](
      this,
      (context, pid, iter) => iter.flatMap(f)
    )
  }
}

val rdd = new RDD[Int]
val result = rdd.flatMap {
  case x if x % 2 == 0 => List(x, x * 2)
  case x => List(x)
}

在上面的代码中,我们定义了一个 RDD 类,并实现了 flatMap 操作。在 flatMap 中,我们使用了模式匹配来判断输入元素 x 是否是偶数,如果是偶数,则将它映射为两个元素,否则映射为一个元素。

除了 RDD,Spark 的 DataFrame 和 Dataset 也广泛使用了模式匹配来实现各种操作。例如,在 DataFrame 中,我们可以使用模式匹配来提取行中的列数据,例如:

val df = Seq((1, "John"), (2, "Mike")).toDF("id", "name")
df.foreach {
  case Row(id: Int, name: String) => println(s"id=$id, name=$name")
}

在上面的代码中,我们使用模式匹配来提取 DataFrame 中的 id 和 name 列,并输出它们的值。

总之,Spark 的核心代码中广泛使用了模式匹配,它是实现各种操作的重要手段,包括 RDD、DataFrame 和 Dataset 等数据结构的实现。

scala模式匹配的语法

Scala 中的模式匹配语法基本上是由 match 关键字和一系列的 case 分支组成的。下面是模式匹配的基本语法:

val x: Any = ...
x match {
  case pattern1 => expression1
  case pattern2 => expression2
  ...
  case patternN => expressionN
}

在上面的语法中,x 是要匹配的值,它的类型为 Any,也可以是其它类型。case 分支中的 pattern 是一个模式,用于匹配 x 的值,并且可以提取出其中的变量。expression 是一个表达式,用于计算匹配成功后的结果。

模式可以是常量、变量、类型、构造函数、元组、列表、数组、对象等。例如,下面是一些常见的模式:

常量模式:例如 case 1 => ...,匹配常量值为 1 的情况。
变量模式:例如 case x => ...,将匹配任何值,并将其绑定到变量 x 上。
类型模式:例如 case x: String => ...,将匹配任何类型为 String 的值,并将其绑定到变量 x 上。
构造函数模式:例如 case Person(name, age) => ...,将匹配类型为 Person 的值,并将其属性值绑定到变量 name 和 age 上。
元组模式:例如 case (x, y) => ...,将匹配任何元组,将第一个元素绑定到变量 x 上,将第二个元素绑定到变量 y 上。
列表模式:例如 case List(x, y, z) => ...,将匹配长度为 3 的列表,并将前三个元素分别绑定到变量 x、y 和 z 上。
数组模式:例如 case Array(x, y, z) => ...,将匹配长度为 3 的数组,并将前三个元素分别绑定到变量 x、y 和 z 上。
对象模式:例如 case p: Person => ...,将匹配类型为 Person 的对象,并将其绑定到变量 p 上。

除了基本模式外,模式匹配还支持一些高级特性,例如模式守卫、变量绑定、通配符和变量模式等,这些特性可以增强模式匹配的表达能力。

总之,Scala 中的模式匹配语法基本上由 match 关键字和一系列的 case 分支组成,可以匹配各种数据类型和结构,并支持一些高级特性来增强表达能力。

类型模式:例如 case x: String => …,将匹配任何类型为 String 的值,并将其绑定到变量 x 上。

是的,类型模式是模式匹配的一种常见形式,用于匹配指定类型的值,并将其绑定到变量上。语法形式为 case x: Type => …,其中 Type 是指要匹配的类型,x 是要绑定的变量名。

例如,下面的示例代码展示了如何使用类型模式来匹配字符串类型的值:

val x: Any = "hello"
x match {
  case str: String => println(s"Length of $str is ${str.length}")
  case _ => println(s"$x is not a string")
}

在上面的代码中,我们首先定义了一个 Any 类型的变量 x,并将其赋值为字符串 “hello”。然后使用模式匹配来检查 x 是否是字符串类型,并将其绑定到变量 str 上,在匹配成功的分支中输出字符串的长度。如果 x 不是字符串类型,则匹配 _ 分支,并输出相应的信息。

需要注意的是,类型模式只能匹配类型,不能用于提取变量。如果需要提取变量,需要使用其它类型的模式,例如构造函数模式、元组模式、列表模式、数组模式等。

总之,类型模式是模式匹配的一种常见形式,用于匹配指定类型的值,并将其绑定到变量上。它可以方便地检查和处理不同类型的值,提高代码的健壮性和可读性。

构造函数模式:例如 case Person(name, age) => …,将匹配类型为 Person 的值,并将其属性值绑定到变量 name 和 age 上。

构造函数模式是 Scala 模式匹配中的一种常见形式,用于匹配某个类的对象,并将其属性值绑定到变量上。语法形式为 case classInstance: ClassName => …,其中 classInstance 是要匹配的类实例,ClassName 是要匹配的类名,可以是 case 类或普通类。

例如,下面的示例代码展示了如何使用构造函数模式来匹配 Person 类的对象,并将其属性值绑定到变量 name 和 age 上:

case class Person(name: String, age: Int)

val person: Person = Person("Alice", 30)

person match {
  case Person(name, age) => println(s"$name is $age years old")
  case _ => println("Not a person")
}

在上面的代码中,我们首先定义了一个 case 类 Person,它有两个属性 name 和 age。然后创建了一个 Person 类的对象,并将其赋值给变量 person。接下来使用模式匹配来检查 person 是否是 Person 类型的对象,并将其属性值绑定到变量 name 和 age 上,在匹配成功的分支中输出相应的信息。如果 person 不是 Person 类型的对象,则匹配 _ 分支,并输出相应的信息。

需要注意的是构造函数模式只能匹配 case 类或普通类,而不能匹配 trait、object 或其它类型的值。如果需要匹配其它类型的值,需要使用其它类型的模式,例如类型模式、元组模式、列表模式、数组模式等。

总之,构造函数模式是 Scala 模式匹配中的一种常见形式,用于匹配某个类的对象,并将其属性值绑定到变量上。它可以方便地检查和处理不同类的对象,提高代码的健壮性和可读性。

元组模式:例如 case (x, y) => …,将匹配任何元组,将第一个元素绑定到变量 x 上,将第二个元素绑定到变量 y 上。

是的,元组模式是 Scala 模式匹配中的一种常见形式,用于匹配元组类型的值,并将其中的元素绑定到变量上。语法形式为 case (x1, x2, …, xn) => …,其中 (x1, x2, …, xn) 是要匹配的元组,x1, x2, …, xn 是要绑定的变量名。

例如,下面的示例代码展示了如何使用元组模式来匹配长度为 2 的元组,并将其第一个元素绑定到变量 x 上,将第二个元素绑定到变量 y 上:

val tuple = (1, "hello")

tuple match {
  case (x, y) => println(s"x=$x, y=$y")
  case _ => println("Not a tuple")
}

在上面的代码中,我们首先定义了一个长度为 2 的元组,并将其赋值给变量 tuple。然后使用模式匹配来检查 tuple 是否是长度为 2 的元组,并将其第一个元素绑定到变量 x 上,将第二个元素绑定到变量 y 上,在匹配成功的分支中输出相应的信息。如果 tuple 不是长度为 2 的元组,则匹配 _ 分支,并输出相应的信息。

需要注意的是,元组模式可以匹配任意长度的元组,但是其中的元素个数必须和模式中的变量个数保持一致。如果元组的长度和模式中的变量个数不一致,模式匹配将会失败。

总之,元组模式是 Scala 模式匹配中的一种常见形式,用于匹配元组类型的值,并将其中的元素绑定到变量上。它可以方便地检查和处理元组类型的值,提高代码的健壮性和可读性。

列表模式:例如 case List(x, y, z) => …,将匹配长度为 3 的列表,并将前三个元素分别绑定到变量 x、y 和 z 上。

是的,列表模式是 Scala 模式匹配中的一种常见形式,用于匹配列表类型的值,并将其中的元素绑定到变量上。语法形式为 case List(x1, x2, …, xn) => …,其中 List(x1, x2, …, xn) 是要匹配的列表,x1, x2, …, xn 是要绑定的变量名。

例如,下面的示例代码展示了如何使用列表模式来匹配长度为 3 的列表,并将其前三个元素分别绑定到变量 x、y 和 z 上:

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

list match {
  case List(x, y, z) => println(s"x=$x, y=$y, z=$z")
  case _ => println("Not a list")
}

在上面的代码中,我们首先定义了一个长度为 4 的列表,并将其赋值给变量 list。然后使用模式匹配来检查 list 是否是长度为 3 的列表,并将其前三个元素分别绑定到变量 x、y 和 z 上,在匹配成功的分支中输出相应的信息。如果 list 不是长度为 3 的列表,则匹配 _ 分支,并输出相应的信息。

需要注意的是,列表模式只能匹配固定长度的列表,而不能匹配任意长度的列表。如果需要匹配任意长度的列表,可以使用列表头尾模式 case head :: tail => … 或者列表模式中的通配符 case _ => …。

总之,列表模式是 Scala 模式匹配中的一种常见形式,用于匹配列表类型的值,并将其中的元素绑定到变量上。它可以方便地检查和处理列表类型的值,提高代码的健壮性和可读性。

对象模式:例如 case p: Person => …,将匹配类型为 Person 的对象,并将其绑定到变量 p 上。

是的,对象模式是 Scala 模式匹配中的一种常见形式,用于匹配某个类型的对象,并将其绑定到变量上。语法形式为 case x: ClassName => …,其中 ClassName 是要匹配的类名,x 是要绑定的变量名。

例如,下面的示例代码展示了如何使用对象模式来匹配类型为 Person 的对象,并将其绑定到变量 p 上:

case class Person(name: String, age: Int)

val person: Person = Person("Alice", 30)

person match {
  case p: Person => println(s"$p is a person")
  case _ => println("Not a person")
}

在上面的代码中,我们首先定义了一个 case 类 Person,然后创建了一个 Person 类的对象,并将其赋值给变量 person。接下来使用模式匹配来检查 person 是否是 Person 类型的对象,并将其绑定到变量 p 上,在匹配成功的分支中输出相应的信息。如果 person 不是 Person 类型的对象,则匹配 _ 分支,并输出相应的信息。

需要注意的是,对象模式只能匹配某个类型的对象,而不能匹配其它类型的值。如果需要匹配其它类型的值,需要使用其它类型的模式,例如类型模式、构造函数模式、元组模式、列表模式、数组模式等。

总之,对象模式是 Scala 模式匹配中的一种常见形式,用于匹配某个类型的对象,并将其绑定到变量上。它可以方便地检查和处理不同类的对象,提高代码的健壮性和可读性。

概念

可以理解为升级版的java switch

1 java中的switch -case是一个分支结构,用于匹配整型(byte,short,int,char),字符串,枚举. (long类型不可以)
2. 分支带上break,表示跳出分支结构,没有break会继续向下判断
3. 没有default,可能一个都匹配不上.default,一定匹配上一个
public static void main(String[] args) {
        int ch=1;
        switch (ch){
            case 1:
                System.out.println("1");break;
            case 2:
                System.out.println("2");break;
            default:
                System.out.println("没有匹配上");
        }

scala没有提供switch case 而是提供了模式匹配的语法

变量名 match{
case=> 分支语句块
case 其他任何类型 => 分支语句块
case _=> "相当于java的default" 
}
不需要break,只会执行其中一条分支

用途

部分替代if else
替代switch等等

用法

匹配字符串

def main(args: Array[String]): Unit = {
    val name = StdIn.readLine()
    name match {
      case "libai" => println(" li bai is a poet")
      case "john" => println("john is a player")
      case _=>println("wrong")
    }
  }

数组匹配
数组匹配时,会先检查长度,如果长度一致,再坚持每个位置是否匹配
如果是值,检查每个值是否相同
如果是变量,则将值赋值给变量

 def main(args: Array[String]): Unit = {
    val names=Array(1,2,3,4)
    names match {
      case Array()=>println("this is a empty array")
      case Array(1,2,3)=>println("是三个元素")
      case Array(3,y,z,m)=>println(3,y)
      case Array(x,y,z,m)=>println(x,y)
      case Array(1,2,3,4)=>println("是四个元素")
      case _=>println("no match")
    }
  }

元组匹配
case后的元组的长度必须和要匹配的变量长度一致

  def main(args: Array[String]): Unit = {
  val t1 = (2, 3, 1, 4)
  t1 match {
    case (1, 2, 3, 4) => println("match 1")
    case (_, _, _, _) => println("match 2")
    case (2, _, _, _) => println("match 3")
  }
}

类型匹配
1 类型匹配时,case后的值是类型名,必须带上一个变量名
2 类型的模式匹配可以完全替代isInstanceOf[]

def main(args: Array[String]): Unit = {
    val a1=Array(1,1.5,Array(1,2),"hello")
    val ele=a1(Random.nextInt(a1.length))
    println(ele)
    ele match {
      case x:Int=>println("this is Int type "+x)
      case y:Double=>println("this is double type "+y)
      case m:Array[Int]=>println("this is Array type "+m)
      case n:String=>println("this is string type "+n)
      case _=>println("no match")
    }
  }

样例类匹配
连类都可以匹配,这个有点6了.
什么是样例类?

1 是一种特殊的类
2 使用case class修饰
3 会自动提供一个伴生object,object中有apply方法,unapply方法
还会在类中生成copy方法,toString方法,hashCode方法
4可以提供一个main constructor,参数默认为val声明
5样例类是不可变的
6 样例类必须提供参数列表
object _06TemplateClass {
  def main(args: Array[String]): Unit = {
    val s1=Student("zhangsan",23,"male")
    s1 match {
      case Student("lisi",23,"male")=>println("this is lisi")
      case Student("zhangsan",23,"male")=>println("this is zhangsan")
      case Student(x,y,z)=>println(x)
      case _=>println("no match")
    }
  }
}

case class Student(name:String,age:Int,gender:String)

unapply方法与apply方法

匹配普通类

apply方法通常会被称为注入方法(创建对象),在类的伴生对象中做以些初始化的操作 
apply方法的参数列表不需要和原生类的构造方法参数一致 
unapply方法通常被提取方法,使用户unapply方法可以提取固定数量的对象或值 
unapply方法返回的是一个Option类型,因为unapply除了提取值之外,还有一个目的就是判断对象是否创建成功 
若成功则有值,反之没有值,所有才使用Option做为返回值类型 
ps:只要是object类,默认都是提供apply和unapply方法,是被默认隐式调用

匹配Option

object Test extends  App{
val x=Option("apple","banana")
  x match {
  //只要有值就会执行后面的语句
    case Some(query) =>println(" it is ok")
    case None=>
  }
}

输出结果

 it is ok
object Test extends  App{
val x=Option("apple","banana")
  x match {
  //query代表的是匹配到的结果的一个变量,随便起的名字
    case Some(query) =>println(query)
    case None=>
  }
}

运行结果

(apple,banana)

匹配的简化写法

总结

一句话,匹配什么都可以!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值