常量模式与变量模式
- 功能类似于其他语言的switch语句,但是在match case语句中是可以使用函数,也就意味着
- =>左侧可以是任意的变量和条件表达式
- =>右侧可以是任何复杂的函数
- 一旦匹配到就会执行相应的函数体并且返回结果
- 用法非常的自由,可以应用在很多地方
- match case与if一样是表达式,而不是语句,可以直接赋值给一个变量
object Hello_Pattern_Match {
def main(args: Array[String]): Unit = {
//1
val data = 30
data match {
case 1 => println("First") //这是函数定义与实现的方式 =>左侧可以是变量和条件表达式 =>右侧可以是函数的实现
case 2 => println("Second")
case _ => println("Not know number") //case _ 代表所有的其它情况
} //row result:Not know number
//Scala中的模式匹配和Java中switch case相似
//其区别在于scala在每个匹配完成之后自动break跳出不在往下匹配 等价于Java中的switch ... case : ... ; break;
//2
val result = data match {
case i if i == 1 => "The First" //i 和 number 为val 用于接收传进来的data 他们在声明的时候会被实例化为data的内容
case number if number == 2 => "Second"
case _ => "Not Know Number"
}
println("result="+result) //row result:Not know number
//3
"Spark !".foreach {
c => println(
c match {
case ' ' => "space"
case ch => "Char:" + ch
}
)
}
/**
* Char:S
Char:p
Char:a
Char:r
Char:k
space
Char:!
*/
}
}
Type、Array、List、Tuple模式匹配
object Pattern_Match_More {
def main(args: Array[String]): Unit = {
/**
* 通过模式匹配判断参数的类型
*/
def match_type(t: Any) = t match {
case p: Int => println("It is Integer") //这里的p变量 val p: Int t会赋值给变量p
case p: String => println("It is String, the content is " + p)
case m: Map[_, _] => m.foreach(println) //val m: Map[_, _]
case _ => println("Unknow type!!!")
}
match_type(2) //It is Integer
match_type("Spark") //It is String, the content is Spark
match_type(Map("Scala" -> "Spark")) //(Scala,Spark)
/**
* 模式匹配数组
*/
def match_array(arr: Any) = arr match {
case Array(0) => println("Array" + "0")
case Array(x, y) => println("Array" + x + " " + y) //匹配有两个元素的数组
case Array(0, _*) => println("Array" + "0 ...") //匹配至少是1个元素,并且第一个元素为0的数组 _*表示后面有许多元素
case _ => println("something else")
}
match_array(Array(0)) //Array0
match_array(Array(0, 1)) //Array0 1
match_array(Array(0, 1, 2, 3, 4, 5, 6)) //Array0 ...
/**
* 模式匹配List
*/
def match_list(lst: Any) = lst match {
case 0 :: Nil => println("List" + "0") //匹配有一个元素的且为0的集合
case x :: y :: Nil => println("List" + x + " " + y) //匹配有两个元素的集合
case 0 :: tail => println("List" + "0 ...") //x :: tail 表示开头的元素为0 tail表示剩下的若干个元素 匹配至少有一个元素的集合
case _ => println("something else")
}
match_list(List(0)) //List0
match_list(List(0, 1)) //List0 1
match_list(List(0, 1, 2, 3, 4, 5)) //List0 ...
/**
* 模式匹配Tuple元祖
*/
def match_tuple(tuple: Any) = tuple match {
case (0, _) => println("Tuple" + "0") //匹配第一个元素为0,第二个元素任意
case (x, 0) => println("Tuple:" + x)
case _ => println("something else")
}
match_tuple((0, "Scala")) //Tuple0
match_tuple((2, 0)) //Tuple:2
match_tuple((0, 1, 2, 3, 4, 5)) //something else
}
}
Scala提取器Extractor
- 提取器Extractor其实是调用了伴生对象中的unapply()方法
- unapplyf()方法其实就是apply()方法的反向操作,将构造器中的参数拿出来
- scala中Array数组的模式匹配的原理就是用了unapply()方法
object ExtractorOps {
def main(args: Array[String]): Unit = {
def match_array(arr: Any) = arr match {
case Array(0) => println("Array" + "0")
case Array(x, y) => println("Array" + x + " " + y) //匹配有两个元素的数组
case Array(0, _*) => println("Array" + "0 ...") //匹配至少是1个元素,并且第一个元素为0的数组 _*表示后面有许多元素
case _ => println("something else")
}
match_array(Array(0)) //Array0 //其实模式匹配在工作的时候会提取出0这个元素,拿到模式匹配中去比较,这就是Extractor的作用
match_array(Array(0, 1)) //Array0 1 //同上...
match_array(Array(0, 1, 2, 3, 4, 5, 6)) //Array0 ...
//正则表达式匹配也是一个提取器
val pattern = "([0-9]+) ([a-z]+)".r
"20150626 hadoop" match {
case pattern(num, item) => println(num + ":" + item) //20150626:hadoop
}
}
}
case class
- 当声明样例类case class的时候内部会自动做的事情
- 构造器中的每个参数成员都默认声明为val,也可以显式的声明var(不建议这样做)
- 每个class都会有对应的伴生对象,在伴生对象中提供有apply方法,让我们不用new关键字就能够构造出相应的对象
- 在模式匹配的时候非常重要的是,我们定义要从case class这个对象中提取出内容,提取的方法也是在伴生对象里面unapply,unapply其实是apply的反操作
- 并且提供unapply方法让模式匹配可以工作
- apply是传递值构建对象,unapply是从已经构建的对象中提取内容
- 也会自动生成一些方法,例如:copy、toString、equals、hashCode
- 样例类和其他类完全一样,你可以添加方法和字段,扩展它们,等等
- spark中的worker工作节点和master节点通信的时候,他们就是传递case class和case object,因为他们默认情况下成员的内容是不能修改的,特别适合消息传递
- 当接受消息后可以进行模式匹配,然后进行相应的业务处理(读取当前worker的资源状况)
abstract class Person //抽象类
case class Student(age: Int) extends Person
case class Worker(age: Int, salary: Double) extends Person //样例类
case object Shared extends Person //单例的样例对象
object Case_Class_Object {
def main(args: Array[String]): Unit = {
def caseOps(person: Person) = person match { //匹配的时候:样例类的实例使用(),样例对象不使用圆括号
case Student(age) => println("I am " + age + "years old")
case Worker(_, salary) => println("Wow, I got " + salary)
case Shared => println("No property")
}
//Student这样的定义方式其实是调用了apply方法
caseOps(Student(19)) //I am 19years old
caseOps(Shared) //No property
val worker = Worker(29, 10000.1)
val worker2 = worker.copy(salary = 19.95) //case class有一个copy的方法可以拷贝上一次的值
val worker3 = worker.copy(age = 30)
}
}
嵌套的Case class
- 样例类经常被用于嵌套结构
- 例如:某个商品售卖的物品。有时候我们会将物品捆绑在一起打折销售
abstract class Item
case class Book(description: String, price: Double) extends Item
case class Bundle(description: String, price: Double, items: Item*) extends Item
object Pattern_Match_Case_Class_Nested {
def main(args: Array[String]): Unit = {
def caseclass_nested(person: Item) = person match {
//@表示法将嵌套的值绑到变量上面
//art 是为了提取整个Book对象 相当于的取了个别名 将Book的case class作为一个引用
case Bundle(_, _, art@Book(_, _), rest@_*) => println(art.description + ":" + art.price)
//_* 表示匹配多个 可以有也可以没有
case Bundle(_, _, Book(descr, _), _*) => println("The first description is " + descr)
case _ => println("Oops!")
}
caseclass_nested(
Bundle("1111 Special's", 30.0,
Book("Scala for the Spark Developer", 69.95),
Bundle("Hadoop", 40.0,
Book("Hive", 79.95),
Book("HBase", 32.95)
)
)) //row result: Scala for the Spark Developer:69.95
caseclass_nested(
Bundle(
"1212 Special's",35.0,
Book("Spark for the Impatient", 39.95)
)
) //row result: Spark for the Impatient:39.95
}
}