大資料學習筆記(scala)
1、Scala六大特性
java和scala可以無縫混編(都是基於JVM) 型別推測(不必指定型別,自動推測型別) 支援併發和分散式(Actor) 特質:trait(集結了java中抽象類和介面的產物) 模式匹配(match case :類似於java中的switch case) 高階函式(引數時函式或者返回值是引數)
2、Scala的安裝使用
本教程介紹在Windows下安裝Scala2.10版本。安裝包可以去官網下載。Scala官網。 下載完成之後,解壓在電腦合適位置(記住該位置)。然後配置環境變數(和java配置環境變數一樣) 新建一個系統變數SCALA_HOME,值是Scala安裝包的位置。
編輯Path環境變數,新增;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin
此時scala安裝完畢,使用win+r輸入cmd開啟命令列,然後輸入scala -version可以看到安裝的scala的版本號。測試成功。
3、Scala基礎
1)、資料型別 Byte 8bite的有符號數字,範圍在-128 – 127 Short 16bite的有符號數字,範圍值在-32868 – 32767 Int 32bite的有符號數字,範圍在-21億 – 21億 Long 64bite的有符號數字,範圍在 負的2的16次方 – 2的16次方 Float 32bite 單精度浮點數 Double 64bite 雙精度浮點數 Char 16bite Unicode字元 String 字串 Boolean 布林型別 Unit 表示無值,和其他語言的void相同 Null 空值或者空引用 Nothing 所有其他型別的子型別,表示沒有值 Any 所有型別的超類,任何例項都屬於Any型別。類似於java的Object AnyRef 所有引用型別的超類 AnyVal 所有值型別的超類 Nil 長度為0的List
2)、變數和常量的宣告
定義變數或者常量的時候,可以寫上返回型別,也可以不寫,如下:
變數:var age:Int = 20或者var age2 = 18
常量:val age:Int = 20或者val age2 = 18(常量不可以再次賦值)
3)、類和物件
建立類:
class Person{
val name = "zhangsan"
val age = 18
def sayName() = {
"my name is "+ name
}
}
建立物件:
object Lesson_Class { def main(args: Array[String]): Unit = { val person = new Person() println(person.age); println(person.sayName()) } }
注意:建議類名首字母大寫 ,方法首字母小寫,類和方法命名建議符合駝峰命名法。 scala 中的object是單例物件,相當於java中的工具類,可以看成是定義靜態的方法的類。object不可以傳引數。另:Trait不可以傳引數 scala中的class類預設可以傳引數,預設的傳引數就是預設的建構函式。 重寫建構函式的時候,必須要呼叫預設的建構函式。 class 類屬性自帶getter ,setter方法。 使用object時,不用new,使用class時要new ,並且new的時候,class中除了方法不執行,其他都執行。
4)、if else
Scala中的if else與java中的用法基本一樣。樣例程式碼如下:
val age =18
if (age < 18 ){
println("no allow")
}else if (18<=age&&age<=20){
println("allow with other")
}else{
println("allow self")
}
5)、for,while,do…while
講解Scala的迴圈之前,先講解Scala的一個特性:until和to(主要區別是:until前閉後開,to前閉後閉)
println(1 until 10 ) //不包含最後一個數,列印 1,2,3,4,5,6,7,8,9
println(1 until (10 ,3 )) //步長為3,從1開始列印,列印1,4,7
println(1 to 10 ) //列印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
println(1 to (10 ,2)) //步長為2,從1開始列印 ,1,3,5,7,9
在邏輯上,Scala中的迴圈跟java中的迴圈一樣,只是使用的方式有些區別,下面分別做介紹。 for迴圈
//例子: 列印九九乘法表;相當於java中的雙層for迴圈
for(i <- 1 until 10 ;j <- 1 until 10){
if(i>=j){
print(i +" * " + j + " = "+ i*j+" ")
}
if(i==j ){
println()
}
}
與java中不一樣的是,for裡面可以加判斷,如下:
for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){
println(i)
}
while與dowhile跟java中判斷邏輯一樣,下面貼個簡單的while例子:
var index = 0
while(index < 100 ){
println("第"+index+"次while 迴圈")
index += 1
}
注意點:scala中不能使用count++,count—只能使用count = count+1 ,count += 1 for迴圈用yield 關鍵字返回一個集合val list = for(i <- 1 to 10 ; if(i > 5 )) yield i for迴圈中可以加條件判斷,分號隔開
4、Scala函式
1)、普通函式
函式格式:
def 函式名(變數名:變數型別,...):返回值型別 = {
函式體
}
簡單函式樣例:
def fun (a: Int , b: Int ) : Unit = {
println(a+b)
}
下面是Scala函式的一些規則和注意點:
函式定義語法 用def來定義
可以定義傳入的引數,要指定傳入引數的型別
方法可以寫返回值的型別也可以不寫,會自動推斷,有時候不能省略,必須寫,比如在遞迴函式中或者函式的返回值是函式型別的時候。
scala中函式有返回值時,可以寫return,也可以不寫return,會把函式中最後一行當做結果返回。當寫return時,必須要寫函式的返回值。
如果返回值可以一行搞定,可以將{}省略不寫。(def fun1 (a : Int , b : Int)= a+b)
傳遞給方法的引數可以在方法中使用,並且scala規定方法的傳過來的引數為val的,不是var的。
如果去掉方法體前面的等號,那麼這個方法返回型別必定是Unit的。這種說法無論方法體裡面什麼邏輯都成立,scala可以把任意型別轉換為Unit.假設,裡面的邏輯最後返回了一個string,那麼這個返回值會被轉換成Unit,並且值會被丟棄。
2)、遞迴函式
遞迴函式就是迴圈呼叫自己,下面給出一個求階乘的程式碼:
def fun2(num :Int) :Int= {
if(num ==1)
num
else
num * fun2(num-1)
}
3)、包含引數預設值的函式
預設值的函式中,如果傳入的引數個數與函式定義相同,則傳入的數值會覆蓋預設值。 如果不想覆蓋預設值,傳入的引數個數小於定義的函式的引數,則需要指定引數名稱。
def fun3(a :Int = 10,b:Int) = {
println(a+b)
}
fun3(b=2)
4)、可變引數個數的函式
多個引數用逗號分開。
def fun4(elements :Int*)={
var sum = 0;
for(elem <- elements){
sum += elem
}
sum
}
println(fun4(1,2,3,4))
5)、匿名函式
匿名函式分為有參匿名函式、無參匿名函式、有返回值的匿名函式。(可以將匿名引數的返回給一個val宣告的值,匿名函式不能顯式的宣告返回值)
//有引數匿名函式
val value1 = (a : Int) => {
println(a)
}
value1(1)
//無引數匿名函式
val value2 = ()=>{
println("我愛Angelababy")
}
value2()
//有返回值的匿名函式
val value3 = (a:Int,b:Int) =>{
a+b
}
println(value3(4,4))
6)、巢狀函式
def fun5(num:Int)={
def fun6(a:Int,b:Int):Int={
if(a == 1){
b
}else{
fun6(a-1,a*b)
}
}
fun6(num,1)
}
println(fun5(5))
7)、偏應用函式
偏應用函式是一種表示式,不需要提供函式需要的所有引數,只需要提供部分,或不提供所需引數。
def log(date :Date, s :String)= {
println("date is "+ date +",log is "+ s)
}
val date = new Date()
//想要呼叫log,以上變化的是第二個引數,可以用偏應用函式處理
val logWithDate = log(date,_:String)
logWithDate("log11")
logWithDate("log22")
logWithDate("log33")
8)、高階函式
函式的引數是函式,或者函式的返回型別是函式,或者函式的引數和函式的返回型別都是函式的函式。
//函式的引數是函式
def hightFun(f : (Int,Int) =>Int, a:Int ) : Int = {
f(a,100)
}
def f(v1 :Int,v2: Int):Int = {
v1+v2
}
println(hightFun(f, 1))
//函式的返回是函式
//1,2,3,4相加
def hightFun2(a : Int,b:Int) : (Int,Int)=>Int = {
def f2 (v1: Int,v2:Int) :Int = {
v1+v2+a+b
}
f2
}
println(hightFun2(1,2)(3,4))
//函式的引數是函式,函式的返回是函式
def hightFun3(f : (Int ,Int) => Int) : (Int,Int) => Int = {
f
}
println(hightFun3(f)(100,200))
println(hightFun3((a,b) =>{a+b})(200,200))
//以上這句話還可以寫成這樣
//如果函式的引數在方法體中只使用了一次 那麼可以寫成_表示
println(hightFun3(_+_)(200,200))
9)、柯里化函式
可以理解為高階函式的簡化
def fun7(a :Int,b:Int)(c:Int,d:Int) = {
a+b+c+d
}
println(fun7(1,2)(3,4))
5、Scala字串
Scala中字串String仍是不可變數。StringBuild為可變字串。具體操作與java類似。
6、Scala集合
1)、陣列
建立陣列:
//建立型別為Int 長度為3的陣列
val arr1 = new Array[Int](3)
//建立String 型別的陣列,直接賦值
val arr2 = Array[String]("s100","s200","s300")
//賦值
arr1(0) = 100
arr1(1) = 200
arr1(2) = 300
遍歷陣列:
for(i <- arr1){
println(i)
}
arr1.foreach(i => {
println(i)
})
建立二維陣列:
val secArray = new Array[Array[String]](5)
for(index <- 0 until secArray.length) secArray(index) = new Array[String](3)
2)、list
list是不可變的,對list進行新增刪除或者取值等操作均會返回一個新的list。
val list = List(1,3,5,9)
println(list.contains(9))
val dropList = list.drop(2)
dropList.foreach { println }
val reList = list.reverse
reList.foreach { x => print(x + "\t") }
3)、set
set是一個非重複的集合,若有重複資料,則會自動去重。
val set = Set(1,3,5,8,1,6,5,8)
set.foreach { x => print(x + "\t") }
4)、map
map是K-V鍵值對集合。
//建立map
val map = Map(
"1" -> "bj" ,
2 -> "sh",
3 -> "gz"
)
//map遍歷
for(x <- map){
println("====key:"+x._1+",value:"+x._2)
}
//遍歷key
var keys = map.keys
//獲取key的迭代器
var keyIterator = keys.iterator
while(keyIterator.hasNext){
val key = keyIterator.next()
println(key + "\t" + map.get(key).get)
}
5)、元組
與列表一樣,與列表不同的是元組可以包含不同型別的元素。元組的值是通過將單個的值包含在圓括號中構成的。建立過程可加new關鍵詞,也可不加。
//建立二元組,下面兩句話效果相同
val t2 = new Tuple2(1,"hello")
val tt2 = (1,"hello")
//建立三元組,下面兩句話效果相同
val t3 = Tuple3(2,"bj","come")
val tt3 = (2,"bj","come")
//建立tt3的迭代器
val tupleIte = tt3.productIterator
while(tupleIte.hasNext) print(tupleIte.next + "\t")
//反轉,只針對二元組
val swap = tt2.swap
//toString
println(tt3.toString())
7、Scala trait特性
Scala Trait(特徵)相當於java中抽象類和介面的集合體,不只是具備介面的特徵,還可以定義屬性和方法的實現。一般情況下Scala的類可以繼承多個Trait,從結果來看就是實現了多重繼承。Trait(特徵) 定義的方式與類類似,但它使用的關鍵字是 trait。 繼承的多個trait中如果有同名的方法和屬性,必須要在類中使用“override”重新定義。並且trait中不可以傳引數。
//定義一個trait
trait Read {
val readType = "Read"
val gender = "m"
def read(name:String){
println(name+" is reading")
}
}
//定義第二個trait
trait Listen {
val listenType = "Listen"
val gender = "m"
def listen(name:String){
println(name + " is listenning")
}
}
//定義了一個類繼承上面兩個trait
class Person() extends Read with Listen{
override val gender = "f"
}
object test {
def main(args: Array[String]): Unit = {
val person = new Person()
person.read("zhangsan")
person.listen("lisi")
println(person.listenType)
println(person.readType)
println(person.gender)
}
}
8、Scala 模式匹配
模式匹配類似於java的switch case。Scala的模式匹配不僅可以匹配值還可以匹配型別、從上到下順序匹配,如果匹配到則不再往下匹配、都匹配不上時,會匹配到case _ ,相當於default、match 的最外面的”{ }”可以去掉看成一個語句。
def match_test(m:Any) = {
m match {
case 1 => println("nihao")
case m:Int => println("Int")
case _ => println("default")
}
}
9、Scala 樣例類
使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。實現了類構造引數的getter方法(構造引數預設被宣告為val),當構造引數是宣告為var型別的,它將幫你實現setter和getter方法。 樣例類預設幫你實現了toString,equals,copy和hashCode等方法。 樣例類可以new, 也可以不用new。
case class Person1(name:String,age:Int)
object Lesson_CaseClass {
def main(args: Array[String]): Unit = {
val p = new Person1("zhangsan",10)
}
}
10、Scala Actor
Actor Model是用來編寫平行計算或分散式系統的高層次抽象(類似java中的Thread)讓程式設計師不必為多執行緒模式下共享鎖而煩惱,每個Actors有自己的世界觀,當需要和其他Actors互動時,通過傳送事件和訊息,傳送是非同步的,非堵塞的(fire-andforget),傳送訊息後不必等另外Actors回覆,也不必暫停,每個Actors有自己的訊息佇列,進來的訊息按先來後到排列,這就有很好的併發策略和可伸縮性,可以建立效能很好的事件驅動系統。 Actor的特徵: ActorModel是訊息傳遞模型,基本特徵就是訊息傳遞 訊息傳送是非同步的,非阻塞的 訊息一旦傳送成功,不能修改 Actor之間傳遞時,自己去檢查訊息,而不是一直等待,是非同步非阻塞的
object Scala07 {
def main(args: Array[String]): Unit = {
val actor = new MyActor
actor.start()
actor ! "hello bj"
}
}
class MyActor extends Actor{
def act() = {
while(true){
receive{
case s: String => println(s)
case _ =>println("default")
}
}
}
}