1. 程式人生 > >Scala學習筆記02【陣列、列表、元組、集合和對映】

Scala學習筆記02【陣列、列表、元組、集合和對映】

1、使用型別引數化陣列【Array】

Scala使用new例項化物件或類例項。
當在Scala裡實例化物件,可以使用值和型別把它引數化:parameterize。
引數化的意思是在你建立例項的時候”設定”它。

例如,例項化一個新的java.math.BigInteger並使用值”12345”引數化:

val big = new java.math.BigInteger("12345") 

一個完整例項:

object HelloWorld 
{

    def main(args: Array[String]) 
    {
      val greetStrings = new
Array[String](3) greetStrings(0) = "Scala: Hello" greetStrings(1) = ", " greetStrings(2) = "world!\n" for (i <- 0 to 2) print(greetStrings(i)) } } //輸出結果:Scala: Hello, world!

Scala裡的陣列是通過把索引放在圓括號裡面訪問的,而不是像Java那樣放在方括號裡。所以陣列的第零個元素是greetStrings(0),不是greetStrings[0]。

這幾行程式碼演示了搞明白Scala如何看待val的意義的重要概念。當你用val定義一個變數,那麼這個變數就不能重新賦值,但它指向的物件卻仍可以改變。

在本例中,你不能把greetStrings重新賦值成不同的陣列;greetStrings將永遠指向那個它被初始化時候指向的同一個Array[String]例項。
但是你能一遍遍修改那個Array[String]的元素,因此陣列本身是可變的。

表示式:

for (i <- 0 to 2)
      print(greetStrings(i)) 

這個for表示式的第一行程式碼演示了Scala的另一個通用規則:
如果方法僅帶一個引數,你可以不帶點或括號的呼叫它。
to實際上是帶一個Int引數的方法:程式碼0 to 2被轉換成方法呼叫(0).to(2)。

Scala沒有操作符過載,在Scala直譯器裡輸入1 + 2,你實際上正在Int物件1上呼叫一個名為+的方法,並把2當作引數傳給它。
也可以使用傳統的方法呼叫語法把1 + 2替代寫成(1).+(2)。

//Scala通常可以更簡潔的方法創造和初始化:

val numNames = Array("zero", "one", "two")

//實際上更羅嗦的呼叫同樣的apply方法的辦法是:

val numNames2 = Array.apply("zero", "one", "two") 

2、使用列表【List】

Scala陣列是一個所有物件都共享相同型別的可變序列。比方說Array[String]僅包含String。儘管例項化之後你無法改變Array的長度,它的元素值卻是可變的。因此,Array是可變的物件。

Scala的List類是共享相同型別的不可變物件序列。

和陣列一樣,List[String]包含的僅僅是String。
Scala的List不同於Java的java.util.List,總是不可變的(而Java的List可變)。

//建立一個Scala的List很簡單

val oneTwoThree = List(1, 2, 3)

上述程式碼完成了一個新的叫做oneTwoThree的val,並已經用帶有整數元素值1,2和3的新List[Int]初始化。

這個List可以這麼用:

val oneTwo = List(1, 2)  
val threeFour = List(3, 4) 
val oneTwoThreeFour = oneTwo ::: threeFour  

println(oneTwo + " 和 " + threeFour + " 是不可變的")  
println("看, " + oneTwoThreeFour + "是個新列表了")

//執行結果:
List(1, 2) 和 List(3, 4) 是不可變的
看, List(1, 2, 3, 4)是個新列表了

List最常用的操作符是發音為”cons”的” :: “. 例如,

val twoThree = list(2, 3)
val oneTwoThree = 1 :: twoThree  
println(oneTwoThree) 

//結果為:List(1, 2, 3) 

類List沒有提供append操作。
如果你想通過新增元素來構造列表:
I、字首進去,完成之後再呼叫reverse;
II、使用ListBuffer,一種提供append操作的可變列表,完成之後呼叫toList。

3、使用元組【Tuple】

另一種有用的容器物件是元組:tuple。與列表一樣,元組也是不可變的,但與列表不同,元組可以包含不同型別的元素。

列表應該是List[Int]或List[String]的樣子,元組可以同時擁有Int和String。

Scala裡你可以簡單地返回一個元組。
而且這麼做的確簡單:例項化一個裝有一些物件的新元組,只要把這些物件放在括號裡,並用逗號分隔即可。
一旦你已經例項化了一個元組,你可以用點號,下劃線和一個基於1的元素索引訪問它。

一個例子:

val pair = (99, "Luftballons")  //Scala推斷元組型別為Tuple2[Int, String],並把它賦給變數pair。
println(pair._1)                //訪問_1欄位,從而輸出第一個元素,99。
println(pair._2)                

//執行結果
99
Luftballons

元組第一個元素是以99為值的Int,第二個是”luftballons”為值的String。

元組的實際型別取決於它含有的元素數量和這些元素的型別。
因此,(99, “Luftballons”)的型別是Tuple2[Int, String]。

類似地,(‘u’, ‘r’, ‘the’, 1, 4, “me”)是Tuple6[Char, Char, String, Int, Int, String]。

訪問元組的元素

為什麼你不能像訪問List裡的元素那樣訪問元組的,就像pair(0)?
因為List的apply方法始終返回同樣的型別,但是元組裡的或許型別不同。
_1可以有一個結果型別,_2是另外一個。
另:元組元素編號從1開始。

4、使用Set和Map

當問題討論到集和對映,Scala同樣提供了可變和不可變的替代品,不過用了不同的辦法。

對於集和對映,Scala把可變性建模在類繼承中。

例如,Scala的API包含了集的一個基本特質:trait,特質這個概念接近於Java的介面。

Scala於是提供了兩個子特質,一個是可變的集,另一個是不可變的集。這三個特質都共享同樣的簡化名,Set。

如果你想要使用HashSet,你可以根據你的需要選擇可變的或不可變的變體。

創造集的預設方法例項:

var jetSet = Set("Boeing", "Airbus")  //定義了名為jetSet的新var,包含兩個字串
jetSet += "Lear"                      // jetSet = jetSet + "Lear" 
println(jetSet.contains("Cessna"))    //列印輸出集是否包含字串"Cessna"。
println(jetSet.contains("Lear"))      //列印輸出集是否包含字串"Lear"。

//執行結果:
false
true

需要不可變集,就需要使用一個引用:import,如下所示:

import scala.collection.mutable.Set  

val movieSet = Set("Hitch", "Poltergeist")  
movieSet += "Shrek" 
println(movieSet)  

//執行結果:
Set(Poltergeist, Shrek, Hitch)

需要一個不可變的HashSet,你可以這麼做:

import scala.collection.immutable.HashSet  
val hashSet = HashSet("Tomatoes", "Chilies")  
println(hashSet + "Coriander") 

//執行結果
Set(Chilies, Tomatoes, Coriander)

Map是Scala裡另一種有用的集合類。
和集一樣,Scala採用了類繼承機制提供了可變的和不可變的兩種版本的Map。

scala.collection包裡面有一個基礎Map特質和兩個子特質Map:
可變的Map在scala.collection.mutable裡,不可變的在scala.collection.immutable裡。

可變對映的創造過程:

import scala.collection.mutable.Map  

val treasureMap = Map[Int, String]()  
treasureMap += (1 -> "我在")  
treasureMap += (2 -> "學習")  
treasureMap += (3 -> "Scala")  
println(treasureMap(1) + treasureMap(2) + treasureMap(3)) 

//執行結果:
我在學習Scala.

至於不可變對映,就不用引用任何類了,因為不可變對映是預設的,程式碼例子:

val romanNumeral = Map(      
        1 -> "我", 2 -> "是", 3 -> "缺", 4 -> "省", 5 -> "的" )  
println(romanNumeral(1) + romanNumeral(2) + romanNumeral(3) + romanNumeral(4) + romanNumeral(5))  

//執行結果:
我是預設的