四天過完scala語法(第一天)
第三章 scala 基礎
1. 宣告值和變數
val:是不可變的,在宣告時就必須被初始化,而且初始化以後就不能再賦值;
var:是可變的,宣告的時候需要進行初始化,初始化以後還可以再次對其賦值。(注意:var變數在宣告的時候也需要初始化)
val myStr = "Hello World!"
注意的是,儘管我們在第1行程式碼的宣告中,沒有給出myStr是String型別,但是,Scala具有“型別推斷”能力,可以自動推斷出變數的型別。
當然,我們也可以顯式宣告變數的型別:
val myStr2 : String = "Hello World!"
需要說明的是,上面的String型別全稱是java.lang.String,也就是說,Scala的字串是由Java的String類來實現的,因此,我們也可以使用java.lang.String來宣告,具體如下:
val myStr3 : java.lang.String = "Hello World!"
但是,為什麼可以不用java.lang.String,而只需要使用String就可以宣告變數呢?這是因為,在每個應用程式中,Scala都會自動新增一些引用,這樣,就相當於在每個程式原始檔的頂端都增加了一行下面的程式碼:
- import java.lang._ //java.lang包裡面所有的東西
2. 基本資料型別和操作
Scala的資料型別包括:Byte、Char、Short、Int、Long、Float、Double和Boolean。和Java不同的是,在Scala中,這些型別都是“類”,並且都是包scala的成員,比如,Int的全名是scala.Int。對於字串,Scala用java.lang.String類來表示字串。
這裡要明確什麼是“字面量”?字面量包括整數字面量、浮點數字面量、布林型字面量、字元字面量、字串字面量、符號字面量、函式字面量和元組字面量。舉例如下:
- val i = 123 //123就是整數字面量
- val i = 3.14 //3.14就是浮點數字面量
- val i = true //true就是布林型字面量
- val i = 'A' //'A'就是字元字面量
- val i = "Hello" //"Hello"就是字串字面量
Scala允許對“字面量”直接執行方法,比如:
- 5.toString() //產生字串"5"
- "abc".intersect("bcd") //輸出"bc"
上面的intersect()方法用來輸出兩個字串中都存在的字元。
操作符
在Scala中,可以使用加(+)、減(-) 、乘(*) 、除(/) 、餘數(%)等操作符,而且,這些操作符就是方法。例如,5 + 3和(5).+(3)是等價的,也就是說:
a 方法 b
a.方法(b)
上面這二者是等價的。前者是後者的簡寫形式,這裡的+是方法名,是Int類中的一個方法。具體程式碼如下:
- scala> val sum1 = 5 + 3 //實際上呼叫了 (5).+(3)
- sum1: Int = 8
- scala> val sum2 = (5).+(3) //可以發現,寫成方法呼叫的形式,和上面得到相同的結果
- sum2: Int = 8
需要注意的是,和Java不同,在Scala中並沒有提供++和--操作符,當需要遞增和遞減時,可以採用如下方式表達:
- scala> var i = 5;
- i: Int = 5
- scala> i += 1 //將i遞增
- scala> println(i)
- 6
此外,也可以使用關係和邏輯操作,比如,大於(>)、小於(<)、大於等於(>=)和小於等於(<=),會產生Boolean型別的結果。
3. Range
在執行for迴圈時,我們經常會用到數值序列,比如,i的值從1迴圈到5,這時就可以採用Range來實現。Range可以支援建立不同資料型別的數值序列,包括Int、Long、Float、Double、Char、BigInt和BigDecimal等。
在建立Range時,需要給出區間的起點和終點以及步長(預設步長為1)。下面通過幾個例項來介紹:
(1)建立一個從1到5的數值序列,包含區間終點5,步長為1
- scala> 1 to 5
- res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
之前我們已經介紹過,在Scala中允許對“字面量”直接執行方法,所以,上面的程式碼,也可以用下面的程式碼來實現:
- scala> 1.to(5)
- res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
(2)建立一個從1到5的數值序列,不包含區間終點5,步長為1
- scala> 1 until 5
- res1: scala.collection.immutable.Range = Range(1, 2, 3, 4)
(3)建立一個從1到10的數值序列,包含區間終點10,步長為2
- scala> 1 to 10 by 2
- res2: scala.collection.immutable.Range = Range(1, 3, 5, 7, 9)
(4)建立一個Float型別的數值序列,從0.5f到5.9f,步長為0.8f
- scala> 0.5f to 5.9f by 0.8f
- res3: scala.collection.immutable.NumericRange[Float] = NumericRange(0.5, 1.3, 2.1, 2.8999999, 3.6999998, 4.5, 5.3
4. 列印語句
在Scala程式設計中,經常需要用到列印語句。
print("My name is:")
print("Ziyu")
上述程式碼執行後,會得到連在一起的一行結果,如下:
My name is Ziyu
如果要每次列印後追加一個換行符,實現換行的效果,就要採用println語句,如下:
println("My name is:")
println("Ziyu")
上述程式碼執行後,會得到兩行結果,如下:
My name is
Ziyu
如果要列印整型變數的值,可以使用下面語句:
val i = 7
println(i)
此外,Scala還帶有C語言風格的格式化字串的printf函式:
val i = 5;
val j = 8;
printf("My name is %s. I hava %d apples and %d eggs.\n","Ziyu",i,j)
上面語句執行後會得到如下結果:
My name is Ziyu. I hava 5 apples and 8 eggs.
更多關於printf函式的使用方法,讀者可以參考C語言書籍。
總結,scala可以使用 print, println, printf。
5. 讀寫檔案
Scala需要使用java.io.PrintWriter實現把資料寫入到文字檔案。
假設當前正使用使用者名稱hadoop登入Linux系統,開啟Scala直譯器進入命令提示符狀態後,輸入以下程式碼:
- scala> import java.io.PrintWriter
- import java.io.PrintWriter //這行是Scala直譯器執行上面語句後返回的結果
- scala> val out = new PrintWriter("output.txt")
- out: java.io.PrintWriter = java.io.PrintWriter@25641d39 //這行是Scala直譯器執行上面語句後返回的結果
- scala> for (i <- 1 to 5) out.println(i)
- scala> out.close()
上面程式碼中,new PrintWriter("output.txt")中只給出了檔名,並沒有給出檔案路徑,採用相對路徑,這時,檔案就會被儲存到啟動Scala REPL時的當前目錄下。比如,如果我們是進入“/home/hadoop”使用者目錄,在這個目錄下啟動進入了Scala REPL互動式執行環境,則上面程式碼執行結束後,可以在hadoop使用者的工作目錄“/home/hadoop/”下找到新生成的這個output.txt檔案。為了檢視這個檔案,我們可以在當前“終端”視窗的基礎上,再新建一個終端視窗,你可以在當前終端視窗的左上角看到一個選單,點選“終端”,選擇“新建終端”,就可以開啟第二個命令列終端視窗(用來檢視檔案)。
現在,讓我們切換到第二個終端視窗,然後,輸入下面命令進入到hadoop使用者的工作目錄,並顯示該目錄下的所有檔案和資料夾資訊:
- cd ~
- ls
"~"就表示當前使用者的工作目錄,對於hadoop使用者而言,就是“/home/hadoop/”目錄。
上面命令執行後,就可以發現,“/home/hadoop/”目錄下有個新生成的這個output.txt檔案,下面使用cat命令檢視該檔案內容:
- cat output.txt
需要注意的是,必須要執行out.close()語句,才會看到output.txt檔案被生成,如果沒有執行out.close()語句,我們就無法看到生成的output.txt檔案。
如果我們想把檔案儲存到一個指定的目錄下,就需要給出檔案路徑,程式碼如下:
- scala> import java.io.PrintWriter
- import java.io.PrintWriter //這行是Scala直譯器執行上面語句後返回的結果
- scala> val out = new PrintWriter("/usr/local/scala/mycode/output.txt")
- out: java.io.PrintWriter = java.io.PrintWriter@25641d39 //這行是Scala直譯器執行上面語句後返回的結果
- scala> for (i <- 1 to 5) out.println(i)
- scala> out.close()
上述過程執行結束後,就可以到“/usr/local/scala/mycode/”這個目錄下找到output.txt檔案。
讀取文字檔案中的行
可以使用Scala.io.Source的getLines方法實現對檔案中所有行的讀取。
仍然假設當前是用hadoop使用者登入了Linux系統,並且使用scala命令啟動了Scala直譯器,現在,我們要把上面剛生成的、在hadoop使用者工作目錄下的output.txt檔案讀取出來,下面給出了完整的讀取檔案例項程式碼:
- scala> import scala.io.Source
- import scala.io.Source //這行是Scala直譯器執行上面語句後返回的結果
- scala> val inputFile = Source.fromFile("output.txt")
- inputFile: scala.io.BufferedSource = non-empty iterator //這行是Scala直譯器執行上面語句後返回的結果
- scala> val lines = inputFile.getLines //返回的結果是一個迭代器
- lines: Iterator[String] = non-empty iterator //這行是Scala直譯器執行上面語句後返回的結果
- scala> for (line <- lines) println(line)
- 1
- 2
- 3
- 4
- 5