常量模式与变量模式
功能类似于其他语言的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的时候内部会自动做的事情
apply是传递值构建对象,unapply是从已经构建的对象中提取内容
构造器中的每个参数成员都默认声明为val,也可以显式的声明var(不建议这样做)
每个class都会有对应的伴生对象,在伴生对象中提供有apply方法,让我们不用new关键字就能够构造出相应的对象
在模式匹配的时候非常重要的是,我们定义要从case class这个对象中提取出内容,提取的方法也是在伴生对象里面unapply,unapply其实是apply的反操作
并且提供unapply方法让模式匹配可以工作
也会自动生成一些方法,例如:copy、toString、equals、hashCode
样例类和其他类完全一样,你可以添加方法和字段,扩展它们,等等
spark中的worker工作节点和master节点通信的时候,他们就是传递case class和case object,因为他们默认情况下成员的内容是不能修改的,特别适合消息传递
当接受消息后可以进行模式匹配,然后进行相应的业务处理(读取当前worker的资源状况)
abstract class Person //抽象类case class Student(age: Int) extends Personcase 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 Itemcase class Book(description: String, price: Double) extends Itemcase 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 } }
作者:他与理想国
链接:https://www.jianshu.com/p/e7a148688121