大数据Saprk----Spark基础--Scala的样例类和模式匹配

first Codec

**public class Friend {
	public static void main(String[] args){
		System.out.println("BigData加QQ群:947967114");
	}
}**

1、简单示例
首先我们先做一个简单的例子,假如我们需要一个操作算术表达式类库,解决这个问题的第一步是输入数据,为了简单我们主要集中注意力在变量、数、二元、一元操作符组成的算术表达式上。那么我们做一个简单的程序:
abstract class Expd
case class Var(name:String) extends Expd
case class Number(num:Double) extends Expd
case class Unop(operator:String,arg:Expd) extends Expd
case class BinOp(operator:String,left:Expd,right:Expd) extends Expd
我们定义了一个抽象的基类和四个子类,每一个类都是我们要做的一种表达式,因为每个类的内部都没有定义,所以省略了花括号。
在以上程序中我们看到在class前面加上了一个特殊的修饰符case,在scala里,带有这种修饰符的类叫做样例类,这种类scala会帮我们添加一些语法上的便利。
第一、会给我们添加一个工厂方法,也就是说这种类的构造要比普通的类构造简单一些,以Var为例,可以直接使用如下方式构造。
scala> val varValue=Var(“testVar”)
varValue: Var = Var(testVar)
scala> val testBinOp=BinOp(“testBinOp”,Number(1),Var(“2.0”))
testBinOp: BinOp = BinOp(testBinOp,Number(1.0),Var(2.0))
而不再需要使用new的方式实例化,当然使用new的方式也不会有问题。
第二、参数列表的参数隐式都获得了val属性。因此这里就直接作为了字段处理。
scala> testBinOp.left
res0: Expd = Number(1.0)
第三、编译器帮我们实现了toString、hashCode和equals方法。所以我们可以直接打印实例化的对象、直接对参数的值进行比较。
例如:
scala> println(testBinOp)
BinOp(testBinOp,Number(1.0),Var(2.0))
scala> testBinOp.leftNumber(3)
res6: Boolean = false
而我们普通的类就不会有这些功能:
定义一个普通类
scala> class MyClass(str:String){}
defined class MyClass
实例化
scala> val my=new MyClass(“ssd”)
my: MyClass = MyClass@16eedaa6
打印实例化的结果,可以看到输出的是一长串字母加数字。
scala> println(my)
l i n e 21. line21. line21.read i w iw iwiw$MyClass@16eedaa6
做比较告诉我们错误
scala> my.str
"ddfs"
:13: error: value str is not a member of MyClass
my.str==“ddfs”
^
第四、编译器还会有一个copy方法,用于制作修改过的拷贝,能够制作一个新的实例,这个实例除了一两个属性不一样,其余和元实例完全一样。我们使用带名字的参数给出修改,对于没有给出的任何参数都使用老参数,实现如下:
scala> testBinOp.copy(operator="new ")
res9: BinOp = BinOp(new ,Number(1.0),Var(2.0))

scala> println(testBinOp)
BinOp(testBinOp,Number(1.0),Var(2.0))
我们观察到只做了一个参数的修改,其他的都使用原来定义的参数。这些都是样例类给我们带来的好处,样例类最大的好处是给我们提供了模式匹配。
我们现在想定义几个表达式:负负取正、加0本身、乘1本身。大致过程如下
def simlifyTop(expr:Expd):Expd=expr match{
case Unop("-",Unop("-",e))=>e
case BinOp("+",e,Number(0))=>e
case BinOp("*",e,Number(1))=>e
case _ => expr
}
这里用到了表达式match和java的switch非常像,但是match放在选择器的后面。模式匹配包含case的可选分支,每一个case都是一个模式和一个或者多个表达式,如果模式匹配正确表达式就会被求值。=>用于把模式和表达式分开。
对以上方法进行调用:
scala> val unop:Expd=Unop("-",Unop("-",Number(2)))
unop: Expd = Unop(-,Unop(-,Number(2.0)))
scala> simlifyTop(unop)
res13: Expd = Number(2.0)
2、模式的种类
模式的语法很容易理解,所有的模式跟相应的表达式完全一样。
统配模式
使用(_)表示匹配任何对象。下面展示了一个通配符的例子。
def simlify(expr:Expd)=expr match{
case BinOp(op,left,right)=>println(expr+" is a binary!")
case _ =>
}
3、常量匹配
常量匹配仅匹配自己,例如2、false、"is"都是常量模式,任何val和单例对象都可以被当作常量使用,Nil能且只能匹配空列表。实例如下:
def describe(a:Any)=a match{
case 5=>false
case true => “apple”
case “pear”=>“yellow”
case Nil=>“empty”
case _ => “another”
}
下面是调用:
scala> describe(5)
res14: Any = false

scala> describe(true)
res15: Any = apple

scala> describe(“no”)
res17: Any = another

4、变量匹配
变量模式匹配任何对象。和通配符非常像。不同于通配模式,scala将对应的变量绑定成匹配上的对象。绑定之后就可以用这个变量来对对象进行匹配。

def checkZero(z:Any)=z match{
case 0=>“zero”
case another=>“not zero” + another
}
我们看到another就是一个变量,当来的任何除了0以外的值来的时候自动使用这种方式匹配,这里和_有一个区别,我们这里可以获取到这个变量的值,也就是直接使用another接受了这个变量。
scala> checkZero(0)
res18: String = zero

scala> checkZero(" Not zero")
res20: String = not zero Not zero
我们看到收到并输出了" Not zero"。
在看一个关于常量E和PI的例子:
import math.{E,PI}
scala> E match{
case Pi=> “it is Pi”+Pi
case _=>“OK”
}
res21: String = OK
我们看一下res21: String = OK这个结果,这个结果表明只有String = OK被使用了,case Pi=> “it is Pi”+Pi没有被采用,因为E永远不能等于Pi。

我们知道E、Pi这些在scala内有固定值的。
scala> val pi=math.Pi
pi: Double = 3.141592653589793

直接用变量的方式得到E的值
scala> E match{
case pi=>pi}
res23: Double = 2.718281828459045
如果我们采用了这种方式,然后在变量模式的下面添加一个模式,那么就会出现问题。
scala> E match{
| case pi=>pi
| case => “yes”
| }
:14: warning: patterns after a variable pattern cannot match (SLS 8.1.1
)
case pi=>pi
^
:15: warning: unreachable code due to variable pattern ‘pi’ on line 14
case => “yes”
^
:15: warning: unreachable code
case => “yes”
^
res24: Any = 2.718281828459045
问题告诉我们unreachable 这是一个不能被找到的模式,因为变量模式本身已经匹配了所有的方式,再在变量模式的下边做一个模式是永远也不能被匹配的。
5、构造方法模式
构造方法模式才是匹配模式的厉害之处。一个构造方法模式例如最开始的
case Unop("-",Unop("-",e))=>e。他是由一个名称和一组参数组成,这是一个样例类,这样一种模式首先检查被匹配的对象是否是以这个名称命名的样例类实例,然后在检查这个对象的构造方法是否匹配这些给出的参数模式。
abstract class Expd
case class Var(name:String) extends Expd
case class Number(num:Double) extends Expd
case class Unop(operator:String,arg:Expd) extends Expd
case class BinOp(operator:String,left:Expd,right:Expd) extends Expd
def simlifyTop(expr:Expd):Expd=expr match{
case Unop("-",Unop("-",e))=>e
case BinOp("+",e,Number(0))=>e
case BinOp("*",e,Number(1))=>e
case _ => expr
}
这就是最好的一个构造方法模式的样例。
6、序列、元组模式
匹配的时候使用序列或元组作为原则:
def ListOrTuple(a:Any) =a match{
case List(0,
,
)=> println(“it is a List”)
case List(0,
)=> println(“it is a List”)
case Array(0,_
)=> println(“it is a List”)
case Array(,)=> println(“it is a List”)
case (x,y,z)=>println(“it is a tuple”+x+y+z)
case (s,r)=>println(“it is a tuple”+s)
case another=>println("Not List and tuple " + another)
}
List(0,,)是一个给定数值两个没给的List,List(0,*)是一个给一个数值,还有多个没给的List,Array(0,*)一个给定多个没给的Array。(x,y,z)三个变量的元组,(s,r)两个个变量的元组。another一个变量模式的匹配,表示任何其他情况。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值