Scala基礎
Scala是一門類似Java的多範式語言,集合了面向對象程式設計和函數式程式設計的特性。
使用Scala語言編寫Spark應用程式的考慮:
1)Scala具有強大的并發性,支援函數式程式設計,可以更好的支援分布式系統。在大資料時代,為了提高應用程式的并發性,函數式程式設計日益收到關注;
2)Scala相容Java,可以與Java互操作。Scala代碼檔案會被編譯成Java的class檔案,開發者可以從Scala中調用Java類庫;
3)Scala代碼簡潔優雅;
4)Scala支援高效的互動式程式設計。其提供了互動式解釋器(Read-Eval-Print Loop, REPL),是以在Spark-shell中可進行互動式程式設計。
5)Scala是Spark的開發語言。用Scala語言編寫Spark應用程式可以獲得最好的執行性能。
基本資料類型
1、Scala的資料類型包括:Byte、Char、Short、Int、Long、Float、Double和Boolean(注意首字母大寫)
2、和Java不同的是,在Scala中,這些類型都是"類",并且都是包scala的成員,比如,Int的全名是scala.Int。對于字元串Scala用java.lang.String類來表示字元串
除了以上9種基本類型,Scala還提供了一個Unit類型,類似Java中的void類型。
字面量
val i=123//123就是整數字面量
val i=3.14//3.14就是浮點數字面量
val i=true//true就是布爾型字面量
val i='A'//'A'就是字元字面量
val i="Hello"//"Hello"就是字元串字面量
基本操作
• 算術運算符:加(+)、減(-) 、乘(*) 、除(/) 、餘數(%);
• 關系運算符:大于(>)、小于(<)、等于(==)、不等于(!=)、大于等于(>=)、小于等于(<=)
• 邏輯運算符:邏輯與(&&)、邏輯或(||)、邏輯非(!);
• 位運算符:按位與(&)、按位或(|)、按位異或(^)、按位取反(~)等
• 指派運算符:=及其與其它運算符結合的擴充指派運算符,例如+=、%=。
• 操作符優先級:算術運算符 > 關系運算符 > 邏輯運算符 > 指派運算符
變量
Scala有兩種類型的變量
1)val:是不可變的,在聲明時就必須被初始化,而且初始化以後就不能再指派。
2)var:是可變的,聲明的時候需要進行初始化,初始化以後還可以再次對其指派。
基本文法:
val 變量名:資料類型 = 初始值
var 變量名:資料類型 = 初始值
但是,Scala有類型推斷機制
輸入和輸出
控制台輸入輸出
從控制台讀取資料
• 從控制台讀取資料方法:readInt、readDouble、readByte、readShort、readFloat、readLong、readChar readBoolean及readLine,分别對應9種基本資料類型,其中前8種方法沒有參數,readLine可以不提供參數,也可以帶一個字元串參數的提示
• 所有這些函數都屬于對象scala.io.StdIn的方法,使用前必須導入,或者直接用全稱進行調用
向控制台輸出資訊方法
• print()和println(),可以直接輸出字元串或者其它資料類型,其中println在末尾自動換行。
也有printf函數
s字元串和f字元串:Scala提供的字元串插值機制,以友善在字元串字面量中直接嵌入變量的值。
基本文法:
s " …$變量名… "
或
f " …$變量名%格式化字元… "
讀寫檔案
寫入檔案
• Scala需要使用java.io.PrintWriter實作把資料寫入到檔案,PrintWriter類提供了print 和println兩個寫方法
讀取檔案
• 可以使用Scala.io.Source的getLines方法實作對檔案中所有行的讀取
控制結構
if條件表達式
和java類似
package cn.itcast.scala
object test {
def main(args: Array[String]) {
val x=3
if(x>0){
println("this is a positive number")
}else if(x==0){
println("this is a zero")
}else{
println("this is a negetive number")
}
}
}
有一點與Java不同的是,Scala中的if表達式的值可以指派給變量
while循環
與Java完全相同
package cn.itcast.scala
object test {
def main(args: Array[String]) {
var i=9
while (i>0){
i-=1
printf("i is %d\n",i)
}
}
}
package cn.itcast.scala
object test {
def main(args: Array[String]) {
var i=0
do{
i+=1
println(i)
}while(i<5)
}
}
for循環
與Java的for循環相比,Scala的for循環在文法表示上有較大的差別,同時,for也不是while循環的一個替代者,而是提供了各種容器周遊的強大功能。
基本結構:
for (變量 <- 表達式) {語句塊}
其中,
“變量<-表達式”
被稱為“生成器(generator)”
for(i<- 1 to 5)
println(i)
for (j <- 1 to 10 by 2)
println(j)
此處,變量不需要關鍵字var或val進行聲明。
1 to 10為一個整數的Range型容器,包含1到10.
守衛(guard)
“守衛(guard)”的表達式:過濾出一些滿足條件的結果。基本文法:
for (變量 <- 表達式 if 條件表達式)
語句塊
for (i <- 1 to 5 if i%2==0)
println(i)
上述語句等價于:
for (i<- 1 to 5)
if (i%2==0)
println(i)
注意:如果需要多個多慮條件,可以增加多個if語句,并用分号隔開。
Scala也支援“多個生成器”的情形,可以用分号把它們隔開,比如:
for(i <- 1 to 5;j <- 1 to 3)
println(i*j)
可以看出實際上實作了循環嵌套
For推導式
• for結構可以在每次執行的時候創造一個值,然後将包含了所有産生值的集合作為for循環表達式的結果傳回,集合的類型由生成器中的集合類型确定。
•
for (變量 <- 表達式) yield {語句塊}
對循環的控制
為了提前終止整個循環或者跳到下一個循環,Scala沒有break和continue關鍵字。Scala提供了一個Breaks類(位于包scala.util.control)。Breaks類有兩個方法用于對循環結構進行控制,即breakable和break:
将需要控制的語句塊作為參數放在breakable後面,然後,其内部在某個條件滿足時調用break方法,程式将跳出breakable方法。
資料結構
數組Array,元組Tuple,清單List,映射Map,集合Set
數組
數組:一種可變的、可索引的、元素具有相同類型的資料集合。
Scala提供了參數化類型的通用數組類Array[T],其中T可以是任意的Scala類型,可以通過顯式指定類型或者通過隐式推斷來執行個體化一個數組。
可以發現,沒有使用new來生成對象,實際上是因為使用了Scala中的伴生對象的apply方法。
多元數組的建立:調用Array的ofDim方法
val myMatrix = Array.ofDim[Int](3,4) //類型實際就是Array[Array[Int]]
val myCube = Array.ofDim[String](3,2,4) //類型實際是Array[Array[Array[String]]]
可以使用多級圓括号來通路多元數組的元素,例如
myMatrix(0)(1)
傳回第一行第二列的元素
元組
元組是對多個不同類型對象的一種簡單封裝。定義元組最簡單的方法就是把多個元素用逗号分開并用圓括号包圍起來。
使用下劃線“_”加上從1開始的索引值,來通路元組的元素。
val tuple =("BigData",2021,8.24)
println(tuple._1) //傳回BigData
如果需要在方法裡傳回多個不同類型的對象,Scala可以通過傳回一個元組實作。
val (t1,t2,t3)=tuple
print(t1) //傳回BigData
print(t2)
print(t3)
容器
Scala提供了一套豐富的容器(collection)庫,包括序列(Sequence)、集合(Set)、映射(Map)等。
• Scala用了三個包來組織容器類,分别是scala.collection 、scala.collection.mutable和scala.collection.immutable。scala.collection包中的容器通常都具備對應的不可變實作和可變實作。
scala.collection包中容器的宏觀層次結構:
序列
序列(Sequence): 元素可以按照特定的順序通路的容器。序列中每個元素均帶有一個從0開始計數的固定索引位置。
兩種常用的序列:清單List和Range
(1)清單
• 清單: 一種共享相同類型的不可變的對象序列。定義在
scala.collection.immutable
包中
• 不同于Java的
java.util.List
,scala的List一旦被定義,其值就不能改變,是以聲明List時必須初始化
• 清單有頭部和尾部的概念,可以分别使用head和tail方法來擷取
• head傳回的是清單第一個元素的值
• tail傳回的是除第一個元素外的其它值構成的新清單,這展現出清單具有遞歸的連結清單結構
•
strList.head
将傳回字元串”BigData”,
strList.tail
傳回
List ("Hadoop","Spark")
• 構造清單常用的方法是通過在已有清單前端增加元素,使用的操作符為
::
,例如:
val otherList="Apache"::strList
(2)Range
Range類:一種特殊的、帶索引的不可變數字等差序列。其包含的值為從給定起點按一定步長增長(減小)到指定終點的所有數值。
集合set
• 不重複元素的容器(collection)。
• 清單中的元素是按照插入的先後順序來組織的,但是,“集合”中的元素并不會記錄元素的插入順序,而是以“哈希”方法對元素的值進行組織,是以,它允許你快速地找到某個元素
• 集合包括可變集和不可變集,分别位于
scala.collection.mutable
包和
scala.collection.immutable
包,預設情況下建立的是不可變集
var mySet = Set("Hadoop","Spark")
mySet += "Scala"
如果要聲明一個可變集,則需要提前引入scala.collection.mutable.Set
import scala.collection.mutable.Set
val myMutableSet = Set("Database","BigData")
myMutableSet += "Cloud Computing"
映射Map
• 映射(Map):一系列鍵值對的容器。鍵是唯一的,但值不一定是唯一的。可以根據鍵來對值進行快速的檢索
• Scala 的映射包含了可變的和不可變的兩種版本,分别定義在包
scala.collection.mutable
和
scala.collection.immutable
裡。預設情況下,Scala中使用不可變的映射。如果想使用可變映射,必須明确地導入
scala.collection.mutable.Map
如果要擷取映射中的值,可以通過鍵來擷取
對于這種通路方式,如果給定的鍵不存在,則會抛出異常,為此,通路前可以先調用contains方法确定鍵是否存在
疊代器Iterator
• 疊代器(Iterator)不是一個容器,而是提供了按順序通路容器元素的資料結構。
• 疊代器包含兩個基本操作:next和hasNext。next可以傳回疊代器的下一個元素,hasNext用于檢測是否還有下一個元素