1. 程式人生 > >Scala的基礎語法

Scala的基礎語法

1. if/else 表示式

1.1 替代三目運算子

先用 Java 來寫一段三目運算子的程式碼

int i = 10;
int j = i>5?i:5

Scala 由於沒有 Java 的三目運算子(?:),不過好在可以用 if/else 表示式替代它。

scala> val i = 10
i: Int = 10

scala> val j = if (i>5) i else 5
j: Int = 10

上面的程式碼,還可以寫成

scala> val i = 10
i: Int = 10

scala> var j =0
j: Int = 0

scala> if (i>5) j = i else j=5

scala> println (j)
10

不過,這種寫法變數 j 需要定義成 var,因為 val 的變數一旦定義不能被改變略嫌麻煩 , 所以第一種寫法會更好。

1.2 混合型別表示式

scala> val i = 10
i: Int = 10

scala> val j = if (i>5) "String express" else 5
j: Any = String express

scala> println(j)
String express

一般三目運算子肯定是返回同一種類型,但是上述的程式碼在 if 和 else 裡既有String型別又有Int型別。所以,返回的是兩個型別的公共超型別Any。

2. 佔位符_

Scala 可以把下劃線“_”當做一個或多個引數的佔位符,第一個下劃線代表第一個引數,第二個下劃線代表第二個,以此類推。只要每個引數在函式文字內僅出現一次。

先看一段 Java 的程式碼,它將集合的每個元素都乘以2再打印出來。

Integer[] arrays = {1,2,3,4,5};
List<Integer> list = Arrays.asList(arrays);
list.stream().map(it->it*2).forEach(System.out::println);

再用佔位符來簡化上述的 Java 程式碼

scala> val list = Array(1,2,3,4,5)
list: Array[Int] = Array(1, 2, 3, 4, 5)

scala> list.map(_*2).foreach(println)
2
4
6
8
10

通過對比,顯然 Scala 的程式碼更加簡潔。

再來一個例子:多個佔位符

scala> val f1 = (x:Int,y:Int) => x+y
f1: (Int, Int) => Int = $$Lambda$1011/[email protected]

scala> f1(1,2)
res0: Int = 3

用兩個佔位符來簡化上面的程式碼。

scala> val f2 = (_:Int)+(_:Int)
f2: (Int, Int) => Int = $$Lambda$1034/[email protected]

scala> f2(1,2)
res1: Int = 3

3. Array 、 ArrayBuffer 以及多維陣列

Scala 的陣列包括定長陣列 Array,以及不定長陣列 ArrayBuffer。

3.1 Array

scala> val nums = new Array[Int](10) // 所有元素初始化為0
nums: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

scala> val strings = new Array[String](10) // 所有元素初始化為null
strings: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)
scala> val names = Array("tony", "cafei", "aaron")
names: Array[String] = Array(tony, cafei, aaron)

scala> names(0)
res2: String = tony

一旦初始化 Array ,只能修改 Array 中的元素,不能增加或者刪除元素。

3.2 ArrayBuffer

ArrayBuffer類似 Java 中的ArrayList。它是陣列緩衝。

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

scala> val arrayBuffer = new ArrayBuffer[Int]
arrayBuffer: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

scala> arrayBuffer += 0
res7: arrayBuffer.type = ArrayBuffer(0)

scala> arrayBuffer += 1
res8: arrayBuffer.type = ArrayBuffer(0, 1)

scala> arrayBuffer += (2,3,4,5)
res9: arrayBuffer.type = ArrayBuffer(0, 1, 2, 3, 4, 5)

scala> arrayBuffer ++= Array(6,7,8,9,10) // 新增Array需要使用++
res10: arrayBuffer.type = ArrayBuffer(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> arrayBuffer.trimEnd(1) // 刪除最後一個元素

scala> println (arrayBuffer)
ArrayBuffer(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

ArrayBuffer 還支援在任意位置進行新增(insert)和刪除(remove)操作

scala> arrayBuffer.insert(2,100) // 在下標2處插入100

scala> println (arrayBuffer)
ArrayBuffer(0, 1, 100, 2, 3, 4, 5, 6, 7, 8, 9)

scala> arrayBuffer.insert(5,101,102) // 在下標5處插入101,102

scala> println (arrayBuffer)
ArrayBuffer(0, 1, 100, 2, 3, 101, 102, 4, 5, 6, 7, 8, 9)

反之,ArrayBuffer 的 remove 操作是同理。

除此之外, ArrayBuffer 還有 sum、max、min、sorted 等常用函式。

ArrayBuffer 到 Array 的轉換: toArray

scala> arrayBuffer.toArray
res21: Array[Int] = Array(0, 1, 100, 2, 3, 101, 102, 4, 5, 6, 7, 8, 9)

3.3 多維陣列

Scala 多維陣列是通過陣列的陣列來實現的。二維陣列看起來像是Array[Array[Int]]。要構造這樣一個數組,可以用ofDim方法。

二維陣列的定義

scala> val matrix=Array.ofDim[Int](3,4) 
matrix: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0))

三維陣列的定義

scala> val matrix2 = Array.ofDim[Int](3,4,5)
matrix2: Array[Array[Array[Int]]] = Array(Array(Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0)), Array(Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0)), Array(Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0)))

所以,多維陣列的定義: Array.ofDim[型別](維度1, 維度2, 維度3,....)

4. 不可變Map 和 可變Map

4.1 不可變Map

不可變Map位於scala.collection.immutable包中。

假設,我們定義某學生的期末考試分數,它是一個不可改變的Map集合。

scala> val scores = Map("math"->90,"english"->85,"chinese"->80)
scores: scala.collection.immutable.Map[String,Int] = Map(math -> 90, english -> 85, chinese -> 80)

獲取該學生的數學成績

scala> scores("math")
res8: Int = 90

獲取該學生的計算機成績,其實並沒有錄入計算機課程的分數會出現什麼情況呢?

scala> scores("computer")
java.util.NoSuchElementException: key not found: computer
  at scala.collection.immutable.Map$Map3.apply(Map.scala:156)
  ... 30 elided

不出意外地報了一個錯誤。 所以,我們得先判斷一下map裡是否包含計算機課程,包含的話就取出成績,不包含的話只能預設0分,這樣程式碼才安全。

scala> val computer = if (scores.contains("computer")) scores("computer") else 0
computer: Int = 0

這下,命令列就不會報錯了。

4.2 可變Map

可變Map位於scala.collection.mutable包中。 對於剛才的情況,新增該學生計算機的成績。

scala> scores +=("computer"->88)
<console>:13: error: value += is not a member of scala.collection.immutable.Map[String,Int]
       scores +=("computer"->88)

scala是會報錯的,因為scores是不可變map。

重新定義scores,讓它變成可變的map,這樣就可以新增其他課程的成績了。

scala> val scores = scala.collection.mutable.Map("math"->90,"english"->85,"chinese"->80)
scores: scala.collection.mutable.Map[String,Int] = Map(chinese -> 80, math -> 90, english -> 85)

scala> scores +=("computer"->88)
res12: scores.type = Map(computer -> 88, chinese -> 80, math -> 90, english -> 85)

換一個角度,我們來看看如何定義一個空的Map


scala> val map=new scala.collection.mutable.HashMap[String,Int]()
map: scala.collection.mutable.HashMap[String,Int] = Map()

scala> map += ("computer"->88)
res15: map.type = Map(computer -> 88)

scala> map +=  ("math"->90,"english"->85,"chinese"->80)
res16: map.type = Map(computer -> 88, chinese -> 80, math -> 90, english -> 85)

scala> println (map)
Map(computer -> 88, chinese -> 80, math -> 90, english -> 85)

scala> map.getClass
res18: Class[_ <: scala.collection.mutable.HashMap[String,Int]] = class scala.collection.mutable.HashMap

未來,我會單獨再整理一篇集合相關的文章。

5. 元組

元組(Tuple)是不同型別的值的聚集。

定義一個元組:

scala> val tuple = (0,false,"Scala")
tuple: (Int, Boolean, String) = (0,false,Scala)

然後我們可以用方法_1、_2、_3訪問其元素。

scala> println(tuple._1) // 列印第一個元素
0

scala> println(tuple._2) // 列印第二個元素
false

scala> println(tuple._3) // 列印第三個元素
Scala

值得注意的是,元組的索引是從1開始,而陣列的索引是從0開始。

通常,使用模式匹配來獲取元組的元素。

scala> val (first, second, third)=tuple
first: Int = 0
second: Boolean = false
third: String = Scala

如果並不是所有的元素都需要,那麼可以在不需要的元素位置上使用佔位符_:

scala> val (first, second, _ ) = tuple
first: Int = 0
second: Boolean = false