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)
匹配的简化写法
总结
一句话,匹配什么都可以!