Scala學習(一) 快速入門
學習Spark就要學習Scala,今天開始快速學習Scala.直接在這裡做筆記了.
1 Scala基礎與語法
1.1 基本資料型別
8中常見資料型別:Byte
,Char
,Short
,Int
,Long
,Float
,Double
和Boolean
. 這裡的Float
和 Double
的具體區別就是 :
浮點數如0.0f或者0.0F,若沒有 f 字尾則是Double變數
String
也是基本資料型別,它屬於java.lang
包,這個包是預設匯入的.
1.2 Scala變數宣告
Scala通過
var
和val
來宣告變數.其中var
是可以重新賦值的,和普通變數沒啥區別,但是val
賦值一次後不能再賦值,相當於java中的final修飾的變數.
舉個栗子,以val
為例,var
差不多
scala> val i=10
i: Int =10
scala>println(i)
10
scala>i=11 //i是不可變的,所以會報錯
<console>:8:error reassignment to val
i=10
^
scala> val a,b = 1f //scala允許一次定義多個變數,這裡定義兩個Float型別的
a:Int = 10
b:Int = 10
//在定義的時候可以指定資料型別
scala> val i:Int =10
i:Int = 10
1.3 算術操作符介紹
這個和c或者java沒區別,直接上例子
//算術運算子=-*/
scala> 1+2 //在scala中+-*/也是物件的函式,所以也可以這麼呼叫1.+(2)
res0:Int=3
//關係運算符== > >= ...
scala>3==2
res1:Boolean = false
//邏輯運算子 && || !
scala> true&&false
res2:Boolean:false
//位運算子 & | ^ (與/或/異或)
scala> 0^1
res3:1
//賦值運算子 += -= <<= ...
//總的來說就是 A op B ==> A= A op B
scala>var a=3
a:Int=3
scala>a+=2
5
1.4 條件語句
scala中的條件語句是有返回值的,可以將其賦值給某個變數,類似於三目運算子.
if(條件) x else y
當然也可以給x ,y加上花括號
if (條件) {
...
}else {
...
}
舉個例子
scala> val i=if(3>1) 3 else 1
i:Int=3 //3賦值給了變數i
scala>if(x<20){
| println("This is if test")
|}
This is if test
scala中的條件語句在
for
迴圈中或match 模式匹配中可以成為守衛
看下面講迴圈的例子.
1.5 迴圈
與java c一樣的迴圈結構 for
,while
,do-while
等,但是具體寫起來還是有差別的
1.5.1 for 迴圈
for (var <- set)
{
...
}
舉個例子
scala>for(i<- 1 to 10) print(i+" ") //1 to 10 生成Range(1,2,..,10)
1 2 3 4 5 6 7 8 9 10
//1 until 10 生成的不包含尾部,生成的是(1,2,...,9)
scala>for(i<- 1 until 10) print(i+" ")
1 2 3 4 5 6 7 8 9
//for 迴圈中使用守衛
scala>for(i<- 1 to 10 if i%2==0)print(i+" ")
2 4 6 8 10
scala>for(i<- 1 to 10 if i%2==0;if i!=2)print(i+" ") //多個過濾條件用分號隔開.
4 6 8 10
for 迴圈中使用守衛
scala>for(i<- 1 to 10 if i%2==0)print(i+" ")
2 4 6 8 10
scala>for(i<- 1 to 10 if i%2==0;if i!=2)print(i+" ") //多個過濾條件用分號隔開.
4 6 8 10
for迴圈巢狀,這裡和一般的java中的巢狀不一樣.
scala>for(i<- 1 to 5;j<- 1 to 5 if i%2==0)print(i*j+" ")
2 3 4 6 8 10 12 16 20
利用yield
關鍵字返回一個新集合
scala>val v1 = for(i<- 1 to 5)yield i
v1:Scala.collection.immutable.IndexSeq[Int]= Vector(1,2,3,4,5)
1.5.2 while 迴圈
while(條件表示式){
...
}
直接上例子
scala> while(i<=5){
| i +=1
| print(i+ " ")
| }
2 3 4 5 6
注意的是,在
for
和while
中都沒有用到break
和continue
,這是因為在scala中沒有break和continue兩個關鍵字,continue可以通過if條件語句來控制是否要向下執行,而break語句在scala中有特殊的實現
import scala.util.control.Breaks._
import scala.util.Random
object ControlStatementBreak{
def main(args:Array[String]){
breakable{
while(true){
val r = new Random()
val i= r.nextInt(10)
println("i=="+i)
if(i==5){
break
}
}
}
}
}
/*這段程式碼首先import 了 scala.util.control.Breaks._ ,這樣就可以使用
breakable和break語句了.在while語句外面用breakable語句塊包圍了,然後在需
要break的地方呼叫break方法,這裡的break 不是關鍵字,而是一個scala方法,這個
方法會丟擲異常從而中斷迴圈
*/
1.5.3 do-while 迴圈
這個和while類似,和java中do-while和while的迴圈的區別一樣,所以不再贅述.
語法:
do{
迴圈體
}(條件表示式)
嚴格的來說, scala中的
for
被成為表示式,它和if
一樣,可以返回結果,而while
或者do-while
型別的就是迴圈結構,它們返回的結構為Unit型別.
1.6 異常控制
分為捕獲異常和丟擲異常
1.6.1 丟擲異常使用關鍵字 throw
例如
throw new IlleagalArgumentException
1.6.2 捕獲異常
例如:
try{
...
} catch {
case ex:NullPointException=>...
case ...
}
finally{//finally語句不一定會有,如果有一定會執行
println("通常用來釋放資源")
}
舉個例子(檔案讀取)
object ReadFileTest{
def main(args:Array[String]){
try{
val file=Source.fromFile("F://2.txt")
val lines=file.getLines()
for(content<- lines){
println(content)
}
}catch{
case ex:FileNotFoundException=>println("輸入的檔案不存在"+ex)
case ex:Exception=> println(ex)
}finally{
println("通常用來釋放資源")
}
}
}
2. Scala 中Array\Map等資料結構
2.1 定長陣列和可變陣列
預設情況下是定長陣列,若定義可變陣列,需要顯示匯入包
import scala.collection.mutable.ArrayBuffer
定義長度為2 的字串陣列
scala> val arrStr =Array("Scala","Spark")
arrStr: Array[String] = Array(Scala, Spark)
定義長度為3的整數型別陣列,初始值為0
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> val arrBufInt=ArrayBuffer[Int]()
arrBufInt: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
2.2 陣列常用演算法
scala> arrStr(0)="Storm" //直接賦值
scala> arrStr.mkString(",")//指定分隔符
res4: String = Storm,Spark
//將定長陣列變成變長陣列
scala> arrStr.toBuffer
res6: scala.collection.mutable.Buffer[String] = ArrayBuffer(Storm, Spark)
//陣列遍歷
scala> for(i<- 0 until arrStr.length)println(arrStr(i))
Storm
Spark
//或者 類似與java中的增強for
scala> for(elem<- arrStr)println(elem)
Storm
Spark
可變陣列特有操作
scala> arrBufInt+=1 //用+=在尾端新增元素
res10: arrBufInt.type = ArrayBuffer(1)
scala> arrBufInt+=(2,3,4,5) //同時新增多個元素
res11: arrBufInt.type = ArrayBuffer(1, 2, 3, 4, 5)
//用++= 可以直接追加一個集合
scala> arrBufInt++=arrBufInt //將自己追加給自己
res13: arrBufInt.type = ArrayBuffer(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
scala> arrBufInt++=Array(6,7,8)//追加個定長陣列
res14: arrBufInt.type = ArrayBuffer(1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 8)
//移除陣列的最後2個元素
scala> arrBufInt.trimEnd(2)
scala> arrBufInt
res16: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6)
//移除陣列的第三個元素
scala> arrBufInt.remove(2)
res17: Int = 3
//在下標為2的位置開始移除4 個元素
scala> arrBufInt.remove(2,4)
scala> arrBufInt
res19: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
//將變長陣列轉換為定長陣列
scala> val arr=arrBufInt.toArray
arr: Array[Int] = Array(1, 2, 3, 4, 5, 6)
2.3 Map對映
預設情況下scala中使用不可變的對映,可變對映必須匯入
scala.collection.mutable.Map
定義對映:
val mapCase=Map("china"->"beijing","france"->"paris")
scala>val bigData=Map("scala"->35,"hadoop"->30,"spark"->50)
bigData:Scala.collection.immutable.Map[String,Int]=Map(scala->35,hadoop ->30,spark->50)
//獲取key為scala的值
scala>bigData("scala")
res0:Int=35
scala>bigData.contains("hadoop") //判斷是否有key為hadoop的鍵值對
res1:Boolean=true
scala>bigData.getOrElse("spark",70) //若對映中存在包含key為spark的鍵值
//對,如果有就返回對應的值,否則返回70
res2:Int=50
//新增分隔符
scala>bigData.mkString("{",",","}")
res3:Strin{scala->35,hadoop->30,spark->50)
scala>bigData.drop(2) //以下標0開始,返回角標為2的元素
Map(spark->50)
res4:scala.collection.immutable.Map[String,Int]=Map(Spark->50)
構建可變對映
scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map
scala> val bigDataVar=Map("scala"->35,"hadoop"->30,"spark"->50)
bigDataVar: scala.collection.mutable.Map[String,Int] = Map(spark -> 50, hadoop -> 30, scala -> 35)
scala> bigDataVar("spark")
res0: Int = 50
scala> bigDataVar("spark")=100//直接賦值
scala> bigDataVar("spark")
res2: Int = 100
scala> bigDataVar+=("kafka"->69) //在後面新增鍵值對
res3: bigDataVar.type = Map(spark -> 100, hadoop -> 30, scala -> 35, kafka -> 69)
scala> bigDataVar -=("kafka"->69) //刪除鍵值對,書上這個程式碼是錯的
<console>:14: error: type mismatch;
found : (String, Int)
required: String
bigDataVar -=("kafka"->69)
^
scala> bigDataVar -=("kafka") //這麼寫就對了
res6: bigDataVar.type = Map(spark -> 100, hadoop -> 30, scala -> 35)
//遍歷對映
scala> for((k,v)<-bigDataVar)println(k+" "+v)
spark 100
hadoop 30
scala 35
//只打印key
scala> for(k<-bigDataVar.keySet)println(k)
spark
hadoop
scala
2.4 Tuple元組
元組和陣列很像,但是它能包含不同種類型的資料
scala> val tuple1=(1,2,4,5,"hello")
tuple1: (Int, Int, Int, Int, String) = (1,2,4,5,hello)
scala> println(tuple1._1) //列印tuple中的元素
1
2.5 List 列表
和陣列很想,資料型別也都必須保持一致,但是區別如下
- 列表中元素不可變
- 列表表示一個連結串列
//定義一個列表
scala> val fruit:List[String]=List("apples","oranges","pears")
fruit: List[String] = List(apples, oranges, pears)
scala> val nums:List[Int]=List(1,2,4,4)
nums: List[Int] = List(1, 2, 4, 4)
//定義個空列表
scala> val empty:List[Nothing]=List()
empty: List[Nothing] = List()
//定義二維列表
scala> val dim:List[List[Int]]=
| List(
| List(1,2,3),
| List(4,5,6),
| List(7,8,9)
| )
dim: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
定義列表的另一種方式
可以用一個無尾 Nil
和 ::
,相當於c語言中的’null’和’->’
scala>val fruit="apples"::("oranges"::("pears"::Nil))
fruit:List[String]=List(apples,oranges,pears)
//定義一個空列表
scala>val empty=Nil
//定義二維列表
scala>val dim=(1::(2::(3::Nil)))::(4::(5::(6::Nil)))::(7::(8::(9::Nil)))::Nil
dim:List[List[Int]]=List(List(1,2,3),List(4,5,6),List(7,8,9))
列表基本操作
scala> class Test{
| def ops{
| val fruit= "apples"::("oranges"::("pears"::Nil))
| val nums =Nil
| println("Head of fruit "+fruit.head)//head是集合中的第一個元素
| println("Tail of fruit "+fruit.tail) //tail是除了第一個元素外的所有元素的集合
| println("Check if fruit is empty "+fruit.isEmpty)
| println("Chek if nums is empty "+nums.isEmpty)
| }
| }
defined class Test
scala> val t= new Test
t: Test = [email protected]51684c4e
scala> t.ops
Head of fruit apples
Tail of fruit List(oranges, pears)
Check if fruit is empty false
Chek if nums is empty true
串聯列表
串聯列表有三種方法
1. 使用:::
2. 使用 List.:::()
3. 使用 List.concat(list1,list2)
//定義兩個list
scala> val fruit1="apples"::Nil
fruit1: List[String] = List(apples)
scala> val fruit2="orange"::Nil
fruit2: List[String] = List(orange)
//使用方法1
scala> var temp =fruit1:::fruit2
temp: List[String] = List(apples, orange)
//使用方法 2
scala> temp = fruit1.:::(fruit2)
temp: List[String] = List(orange, apples)
//使用方法3
scala> temp=List.concat(fruit1,fruit2)
temp: List[String] = List(apples, orange)
2.7 set集合
set集合同樣也有可變不可變 ,可變匯入scala.collection.mutable.Set
它的操作放發與list很像,直接上例子
scala> var s:Set[Int]=Set() //定義一個set
s: Set[Int] = Set()
scala> var s :Set[Int]=Set(1,3,4,5)
s: Set[Int] = Set(1, 3, 4, 5)
scala> var s =Set(1,3,4,5)
s: scala.collection.immutable.Set[Int] = Set(1, 3, 4, 5)
// 這裡展示基本操作
scala> val book=Set("scala","spark","hadoop")
book: scala.collection.immutable.Set[String] = Set(scala, spark, hadoop)
scala> println("Head of book " + book.head) //與List的head和tail一樣
Head of book scala
scala> println("tail of book "+book.tail)
tail of book Set(spark, hadoop)
scala> book.isEmpty
res2: Boolean = false
其它的集合方法大全的話,這裡就不列了,可以參考後文中的官方連結
2.7 scala官方文件連結
參考文獻
這裡參考書籍是《Spark零基礎實戰》,作者王家林和孔祥瑞.大部分程式碼都是敲過在本機上執行成功的.