1. 程式人生 > >Scala入門到精通—— 第二節Scala基本型別及操作、程式控制結構

Scala入門到精通—— 第二節Scala基本型別及操作、程式控制結構

本節主要內容

  1. Scala基本型別
  2. 基本型別操作
  3. Scala程式控制結構

Scala基本型別

Scala中的基本資料型別如下圖:
這裡寫圖片描述
(來源:Programming in Scala)

從上表中可以看出,Scala的基本資料型別與Java中的基本資料型別是一一對應的,不同的是Scala的基本資料型別頭字母必須大寫,本節以Int、Long、String、Char、Double及Float型別為例介紹Scala的基本型別定義

整數型別變數定義:

//16進制定義法
scala> val x=0x29
x: Int = 41
//十進位制定義法
scala> val x=41
x: Int = 41
//八進位制定義法
scala> 051
res0: Int = 41

浮點型別變數定義:

//Double型別定義,直接輸入浮點數,編譯器會將其自動推斷為Double型別
scala> val doubleNumber=3.141529
doubleNumber: Double = 3.141529
//要定義Float型別浮點數,需要在浮點數後面加F或f
scala> val floatNumber=3.141529F
floatNumber: Float = 3.141529

scala> val floatNumber=3.141529
f floatNumber: Float = 3.141529

浮點型別的變數還可以採用指數表示法,如

//浮點數指數表示法,e也可以是大寫E,0.314529e1與0.314529*10等同
scala> val floatNumber=0.314529e1
floatNumber: Double = 3.14529

字元變數定義:

//字元定義,用''將字元包裹
scala> var charLiteral='A'
charLiteral: Char = A

常用特殊字元包括
\n 換行符,其Unicode編碼為 (\u000A)
\b 回退符,其Unicode編碼為 (\u0008)
\t tab製表符 ,其Unicode編碼(\u0009)
\” 雙引號,其Unicode編碼為 (\u0022)
\’ 單引號,其Unicode編碼為 (\u0027)
\ 反斜杆,其Unicode編碼為(\u005C)

字串變數定義:

//字串變數用""包裹
scala> val helloWorld="Hello World"
helloWorld: String = Hello World

//要定義"Hello World",可以加入轉義符\
scala> val helloWorldDoubleQuote="\"Hello World\""
helloWorldDoubleQuote: String = "Hello World"

//如果希望能夠原樣輸出字串中的內容,則用三個引號"""將字串包裹起來,如
scala> println(""" hello cruel world, \n \\\\ \b \\, I am " experienced" programmer""")
 hello cruel world, \n \\\\ \b \\, I am " experienced" programmer

布林型別定義:

scala> var x=true
x: Boolean = true

Scala基本型別操作

在Scala中一切操作皆方法,這意味著Scala中的一切皆為物件

算術操作:

//整數求和,編譯器會將其轉換為(1).+(2)執行
scala> var sumVlaue=1+2
sumVlaue: Int = 3

//前一語句等同於下列語句
scala> var sumVlaue=(1).+(2)
sumVlaue: Int = 3

//操作符過載,編譯器會將其轉換為(1).+(2L)執行
scala> val longSum = 1 + 2L
longSum: Long = 3

//減法
scala> 1-3
res5: Int = -2

//除法
scala> 1/3
res6: Int = 0

//取模
scala> 1%3
res7: Int = 1

//乘法
scala> 1L*3L
res8: Long = 3

//scala中可以用+ -符號來表示正負數,例如-3 +3,並且可以加入到運算子當中
scala> var y=1+ -3
y: Int = -2

關係運算:

//>運算子
scala> 3 > -3
res12: Boolean = true
//<運算子
scala> 3 < -3
res13: Boolean = false
//<=運算子
scala> 3 <= -3
res14: Boolean = false
//<=運算子
scala> 3 <=3
res15: Boolean = true
//<=運算子
scala> !(3<= -3)
res16: Boolean = true

邏輯運算:

//邏輯與:&&
scala> val bool=true
bool: Boolean = true

scala> bool && bool
res17: Boolean = true
//邏輯或:||
scala> bool || bool
res18: Boolean = true


scala> bool || !bool
res20: Boolean = true

位運算:

// 00000001
// 00000010
// 00000000
scala> 1 & 2
res24: Int = 0

// 00000001
// 00000010
// 00000011
scala> 1 | 2
res24: Int = 3

// 00000001
// 00000011
// 00000010
scala> 1 ^ 3
res24: Int =2

//00000001
//11111110
scala> ~1
res24: Int =-2

//左移位(shift left)
//00000110
//00001100
scala> 6 << 1
res29: Int = 12

//右移位(shift left)
//00000110
//00000011
scala> 6 >> 1
res28: Int = 3

//無符號右移(shift left)
//11111111111111111111111111111111
//00000000000000000000000000000001
scala> -1 >>> 31
res32: Int = 1

物件比較:

scala> 1==1
res34: Boolean = true

scala> 1==1.0
res35: Boolean = true

scala> val x="Hello"
x: String = Hello

scala> val y="Hello"
y: String = Hello

//Scala中的物件比較不同於Java中的物件比較
//Scala基於內容比較,而java中比較的是引用,進行內容比較時須定義比較方法
scala> x==y
res36: Boolean = true

運算子的優先順序:
運算子優先順序如下圖所示,* / %優先順序最高,依次類推
這裡寫圖片描述
圖片來源:Programming in Scala

Scala程式控制結構

if 的使用:

val x= if("hello"=="hell")  1 else 0

while 的使用:

def gcdLoop(x: Long, y: Long): Long = {
        var a = x
        var b = y
        while (a != 0) {
            val temp = a
            a = b % a
            b = temp
        } 
        b
}

do while的使用

var line = ""
do {
    line = readLine()
    println("Read: "+ line)
} while (line != "")

注意:與if不同的是,while與do while不能用作表示式,也即其返回值為Unit,在某些函數語言程式設計語言中,刪除了while與do while程式控制結構,但scala仍然保留了while與do while,可見Scala並不是純函數語言程式設計語言(另外一個重要原因是,scala函式定義時仍然可以用var指定引數)。

//利用if替代while控制結構
//這些做可以減少var變數的使用,程式結構也更簡單,表達能力更強
def gcd(x: Long, y: Long): Long =
if (y == 0) x else gcd(y, x % y)
var line = ""
while ((line = readLine()) != "") // 在Scala中不能這麼用,因為Scala中的賦值操作返回的值是Unit,而""是String型別,不能進行比較,這是函數語言程式設計語言特有的特點
println("Read: "+ line)

for迴圈的使用

scala> val filesHere = (new java.io.File(".")).listFiles
//集合操作方式
scala> for (file <- filesHere)
     | println(file)

//間接呼叫方式(不常用)
for (i <- 0 to filesHere.length - 1)
println(filesHere(i))

//程式中的<-被稱生成器(generator),在執行過程中,集合filesHere中(Array[File])的元素將依次賦給file,file型別為File,列印時呼叫其toString方法將檔名稱打印出來。

scala> val filesHere = (new java.io.File(".")).listFiles
filesHere: Array[java.io.File] = Array(.\.android, .\.idea-build, .\.IdeaIC14, .
\.ivy2, .\.m2, .\.sbt, .\.scala_history, .\AppData, .\Application Data, .\Contac
ts, .\Cookies, .\Desktop, .\Documents, .\Downloads, .\Favorites, .\hello, .\Link
s, .\Local Settings, .\Music, .\My Documents, .\NetHood, .\NTUSER.DAT, .\ntuser.
dat.LOG1, .\ntuser.dat.LOG2, .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.
TM.blf, .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMContainer0000000000
0000000001.regtrans-ms, .\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMCon
tainer00000000000000000002.regtrans-ms, .\ntuser.ini, .\Pictures, .\PrintHood, .
\Recent, .\Roaming, .\Saved Games, .\Searches, .\SendTo, .\target, .\Templates,
.\Videos, .\「開始」選單)

scala> for (file <- filesHere)
     | println(file)
.\.android
.\.idea-build
.\.IdeaIC14
.\.ivy2
.\.m2
.\.sbt
.\.scala_history
.\AppData
.\Application Data
.\Contacts
.\Cookies
.\Desktop
.\Documents
.\Downloads
.\Favorites
.\hello
.\Links
.\Local Settings
.\Music
.\My Documents
.\NetHood
.\NTUSER.DAT
.\ntuser.dat.LOG1
.\ntuser.dat.LOG2
.\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TM.blf
.\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMContainer000000000000000000
01.regtrans-ms
.\NTUSER.DAT{016888bd-6c6f-11de-8d1d-001e0bcde3ec}.TMContainer000000000000000000
02.regtrans-ms
.\ntuser.ini
.\Pictures
.\PrintHood
.\Recent
.\Roaming
.\Saved Games
.\Searches
.\SendTo
.\target
.\Templates
.\Videos
.\「開始」選單

<-生成器對其它型別的集合也適用,

scala> 1 to 5
res39: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)

scala> for(i <- res39) println("Iteration"+i)
Iteration1
Iteration2
Iteration3
Iteration4
Iteration5

也可直接簡寫成
scala> for(i <- 1 to 5) println("Iteration"+i)
Iteration1
Iteration2
Iteration3
Iteration4
Iteration5

//如果不需要5出現,則用
scala> for(i <- 1 until 5) println("Iteration"+i)
Iteration1
Iteration2
Iteration3
Iteration4

在for迴圈結構中還可以加入if進行過濾操作

val filesHere = (new java.io.File(".")).listFiles
for (file <- filesHere if file.getName.endsWith(".scala"))
println(file)
//還可以加入多個過濾條件,用;隔開
for (
file <- filesHere
if file.isFile;
if file.getName.endsWith(".scala")
) println(file)

//多重迴圈的實現:

def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines.toList
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala");
line <- fileLines(file)
if line.trim.matches(pattern)
) println(file +": "+ line.trim)
grep(".*gcd.*")

//前一個for相當於下列語句
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala")
) 
for(
line <- fileLines(file)
if line.trim.matches(pattern)
)
println(file +": "+ line.trim)
grep(".*gcd.*")

生成返回結果

//每次迴圈將結果保留,當整個迴圈執行完畢,所有保留的值將會生成一個集合並返回
scala> def scalaFiles =
     | for {
     | file <- filesHere
     | if file.getName.endsWith(".scala")
     | } yield file
scalaFiles: Array[java.io.File]

//Array[File]到Array[Int]的轉換
scala> val forLineLengths =
     | for {
     | file <- filesHere
     | if file.getName.endsWith(".scala")
     | line <- fileLines(file)
     | trimmed = line.trim
     | if trimmed.matches(".*for.*")
     | } yield trimmed.length
forLineLengths: Array[Int] = Array()

新增公眾微訊號,可以瞭解更多最新Spark、Scala相關技術資訊
這裡寫圖片描述