Scala集合
Scala提供了一套很好的集合實現,提供了一些集合類型的抽象。
Scala 集合分為可變的和不可變的集合。
可變集合可以在適當的地方被更新或擴展。這意味着你可以修改,添加,移除一個集合的元素。而不可變集合類永遠不會改變。不過,你仍然可以模擬添加,移除或更新操作。但是這些操作將在每一種情況下都返回一個新的集合,同時使原來的集合不發生改變。
集合中基本結構:

幾種常用集合類型示例:
-
// 定義整型 List
-
val x = List( 1, 2, 3, 4)
-
-
// 定義 Set
-
var x = Set( 1, 3, 5, 7)
-
-
// 定義 Map
-
val x = Map( "one" -> 1, "two" -> 2, "three" -> 3)
-
-
// 創建兩個不同類型元素的元組
-
val x = ( 10, "Runoob")
-
-
// 定義 Option
-
val x: Option[Int] = Some( 5)
Scala List(列表)
Scala 列表類似於數組,它們所有元素的類型都相同,但是它們也有所不同:列表是不可變的,值一旦被定義了就不能改變,其次列表 具有遞歸的結構(也就是鏈接表結構)而數組不是。
列表的元素類型 T 可以寫成 List[T]。例如,以下列出了多種類型的列表:
-
// 字符串列表
-
val site: List[String] = List( "Sina", "Google", "Baidu")
-
-
// 整型列表
-
val nums: List[Int] = List( 1, 2, 3, 4)
-
-
// 空列表
-
val empty: List[Nothing] = List()
-
-
// 二維列表
-
val dim: List[List[Int]] =
-
List(
-
List( 1, 0, 0),
-
List( 0, 1, 0),
-
List( 0, 0, 1)
-
)
構造列表的兩個基本單位是 Nil 和 ::
Nil 也可以表示為一個空列表。
以上實例我們可以寫成如下所示:(::)符號連接順序是從右到左
-
// 字符串列表
-
val site = "Sina" :: ("Google" :: ("Baidu" :: Nil))
-
-
// 整型列表
-
val nums = 1 :: (2 :: (3 :: (4 :: Nil)))
-
-
// 空列表
-
val empty = Nil
-
-
// 二維列表
-
val dim = ( 1 :: (0 :: (0 :: Nil))) ::
-
( 0 :: (1 :: (0 :: Nil))) ::
-
( 0 :: (0 :: (1 :: Nil))) :: Nil
基本操作
Scala列表有三個基本操作:
- head 返回列表第一個元素
- tail 返回一個列表,包含除了第一元素之外的其他元素:(是一個列表或者Nil)
- isEmpty 在列表為空時返回true
對於Scala列表的任何操作都可以使用這三個基本操作來表達。代碼示例如下:
-
val site = "Sina" :: ("Google" :: ("Baidu" :: Nil))
-
val nums = Nil
-
//打印測試head、tail、isEmpty功能
-
println(site.head)
-
println(site.tail)
-
println(site.isEmpty)
-
println(nums.isEmpty)
打印結果為:
-
Sina
-
List(Google, Baidu)
-
false
-
true
連接列表
你可以使用 ::: 、 List.:::() 或 List.concat() 方法來連接兩個或多個列表。
代碼示例如下:
-
val site1 = "Sina" :: ("Google" :: ("Baidu" :: Nil))
-
val site2 = "Facebook" :: ("Taobao" :: Nil)
-
-
// 使用 ::: 運算符
-
var combine = site1 ::: site2
-
println( "site1 ::: site2 : " + combine )
-
-
// 使用 list.:::() 方法,注意:結果為site2列表元素在前,site1在后
-
combine = site1.:::(site2)
-
println( "site1.:::(site2) : " + combine )
-
-
// 使用 concat 方法
-
combine = List.concat(site1, site2)
-
println( "List.concat(site1, site2) : " + combine )
-
}
打印結果:
-
site1 ::: site2 : List(Sina, Google, Baidu, Facebook, Taobao)
-
site1.:::(site2) : List(Facebook, Taobao, Sina, Google, Baidu)
-
List.concat(site1, site2) : List(Sina, Google, Baidu, Facebook, Taobao)
List.fill()
我們可以使用 List.fill() 方法來創建一個指定重復數量的元素列表:
-
val site = List.fill( 3)("Baidu") // 重復 Runoob 3次
-
println( "site : " + site )
-
-
val num = List.fill( 10)(2) // 重復元素 2, 10 次
-
println( "num : " + num )
打印結果為:
-
site : List(Baidu, Baidu, Baidu)
-
num : List( 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)
List.tabulate()
List.tabulate() 方法是通過給定的函數來創建列表。
方法的第一個參數為元素的數量,可以是二維的,第二個參數為指定的函數,我們通過指定的函數計算結果並返回值插入到列表中,起始值為 0,實例如下:
-
// 通過給定的函數創建 5 個元素
-
val squares = List.tabulate( 6)(n => n * n)
-
println( "一維 : " + squares )
-
-
// 創建二維列表
-
val mul = List.tabulate( 4,5 )( _ * _ )
-
println( "二維 : " + mul )
打印結果為:
-
一維 : List( 0, 1, 4, 9, 16, 25)
-
二維 : List(List( 0, 0, 0, 0, 0), List(0, 1, 2, 3, 4), List(0, 2, 4, 6, 8), List(0, 3, 6, 9, 12))
List.reverse
List.reverse 用於將列表的順序反轉,實例如下:
-
val site = "Sina" :: ("Google" :: ("Baidu" :: Nil))
-
println( "反轉前 : " + site )
-
println( "反轉前 : " + site.reverse )
打印結果為:
-
反轉前 : List(Sina, Google, Baidu)
-
反轉前 : List(Baidu, Google, Sina)
列表緩存(ListBuffer)
List類能夠提供對列表頭部,而非尾部的快速訪問。如果需要向結尾添加對象,則需要先對表頭前綴元素方式反向構造列表,完成之后再調用reverse。
上述問題另一種解決方式就是使用ListBuffer,這可以避免reverse操作。ListBuffer是可變對象,它可以更高效的通過添加元素來構建列表。
使用ListBuffer替代List另一個理由是避免棧溢出風險。
ListBuffer使用示例:
-
val buf: ListBuffer[Int] = new ListBuffer[Int]
-
//往后添加
-
buf += 1
-
buf += 2
-
-
//前綴添加
-
val buf2 = 3 +: buf
-
println(buf2.toString())
-
-
//ListBuffer轉List
-
println(buf2.toList.toString())
List常用方法
- 參考底部附錄:
Scala隊列和棧
隊列
如果你需要先進先出序列,你可以使用Queue(隊列)。Scala集合提供了可變和不可變的Queue。
不可變Queue代碼示例:
-
//使用伴生對象創建一個queue
-
val que = Queue[Int]()
-
-
//使用enqueue為不可變隊列添加元素
-
val que1 = que.enqueue( 1)
-
-
//往隊列添加多個元素,把集合作為enqueue的參數
-
val que2 = que1.enqueue(List( 2,3,4,5))
-
-
//從隊列頭部移除元素,使用dequeue
-
//第一個參數為頭部移除的元素,第二個參數為剩下的隊列
-
val (elem1,que3) = que2.dequeue
-
-
//打印移除的元素
-
println(elem1)
-
-
//打印剩下的隊列
-
println(que3)
打印結果為:
-
1
-
Queue( 2, 3, 4, 5)
可變Queue代碼示例:
-
//使用伴生對象創建一個可變queue
-
var que = scala.collection.mutable.Queue[String]()
-
-
//使用 += 符號添加單個元素
-
que += "A"
-
-
//使用 ++= 符號添加多個元素
-
que ++= List( "B","C","D")
-
-
//使用dequeue移除頭部元素
-
val a = que.dequeue
-
-
//打印移除的元素
-
println(a)
-
-
//打印隊列中剩下的元素
-
print(que)
打印結果:
-
A
-
Queue(B, C, D)
棧
如果需要的是后進先出,你可以使用Stack,它同樣在Scala的集合中有可變和不可變版本。元素的推入使用push,彈出用pop,只獲取棧頂元素而不移除可以使用top。
可變棧示例:
-
//使用Stack類的伴生對象創建Stack對象
-
var stack = scala.collection.mutable.Stack[Int]()
-
-
//往棧stack中壓如元素
-
stack.push( 1)
-
stack.push( 2)
-
stack.push( 3)
-
-
//打印查看棧內元素
-
println(stack)
-
-
//獲取棧頂元素的值
-
val tval = stack. top
-
println("棧頂元素為 : " + tval)
-
-
//移除棧頂元素
-
val pval = stack.pop()
-
println( "移除的棧頂元素為 : " + pval)
-
-
//打印移除棧頂元素后,剩下的棧內元素
-
println(stack)
打印結果:
-
Stack( 3, 2, 1)
-
棧頂元素為 : 3
-
移除的棧頂元素為 : 3
-
Stack( 2, 1)
隊列和棧常用操作
- 參考底部附錄:
Scala Set(集)
- Scala Set(集)是沒有重復的對象集合,所有的元素都是唯一的。
- Scala 集合分為可變的和不可變的集合。
- 默認情況下,Scala 使用的是不可變集合,如果想使用可變集合,需引用 scala.collection.mutable.Set 包。
- 默認引用 scala.collection.immutable.Set。
不可變集合實例如下:
-
val set = Set( 1,2,3)
-
println(set.getClass.getName) //
-
-
println(set.exists(_ % 2 == 0)) //true
-
println(set.drop( 1)) //Set(2,3)
打印結果為:
-
scala.collection.immutable. Set$Set3
-
true
-
Set(2, 3)
如果需要使用可變集合需要引入 scala.collection.mutable.Set:
-
import scala.collection.mutable.Set // 可以在任何地方引入 可變集合
-
-
val mutableSet = Set( 1,2,3)
-
println(mutableSet.getClass.getName) // scala.collection.mutable.HashSet
-
//往集合內添加元素4
-
mutableSet.add( 4)
-
//刪除值為1的元素
-
mutableSet.remove( 1)
-
//添加元素5
-
mutableSet += 5
-
//刪除值為3的元素
-
mutableSet -= 3
-
-
println(mutableSet) // Set(5, 3, 4)
-
-
val another = mutableSet. toSet
-
println(another.getClass.getName) // scala.collection.immutable.Set
注意: 雖然可變Set和不可變Set都有添加或刪除元素的操作,但是有一個非常大的差別。對不可變Set進行操作,會產生一個新的set,原來的set並沒有改變,這與List一樣。 而對可變Set進行操作,改變的是該Set本身,與ListBuffer類似。
Set集合基本操作
Scala Set集合有三個基本操作:
- head 返回集合第一個元素
- tail 返回一個集合,包含除了第一元素之外的其他元素
- isEmpty 在集合為空時返回true
對於Scala集合的任何操作都可以使用這三個基本操作來表達。
代碼示例如下:
-
val site = Set( "Sina", "Google", "Baidu")
-
val nums: Set[Int] = Set()
-
-
println( "head : " + site.head )
-
println( "tail : " + site.tail )
-
println( "isEmpty : " + site.isEmpty )
-
println( "isEmpty : " + nums.isEmpty )
打印結果為:
-
head : Sina
-
tail : Set(Google, Baidu)
-
isEmpty : false
-
isEmpty : true
連接集合
你可以使用 ++ 運算符或 Set.++() 方法來連接兩個集合。如果元素有重復的就會移除重復的元素。實例如下:
-
val site1 = Set( "Sina", "Google", "Baidu")
-
val site2 = Set( "Faceboook", "Taobao")
-
-
// ++ 作為運算符使用
-
var site = site1 ++ site2
-
println( "site1 ++ site2 : " + site )
-
-
// ++ 作為方法使用
-
site = site1.++(site2)
-
println( "site1.++(site2) : " + site )
打印結果為:
-
site1 ++ site2 : Set(Faceboook, Taobao, Sina, Google, Baidu)
-
site1.++(site2) : Set(Faceboook, Taobao, Sina, Google, Baidu)
查找集合中最大與最小元素
你可以使用 Set.min 方法來查找集合中的最小元素,使用 Set.max 方法查找集合中的最大元素。實例如下:
-
val num = Set( 5,6,9,20,30,45)
-
-
// 查找集合中最大與最小元素
-
println( "Set(5,6,9,20,30,45) 最小元素是 : " + num.min )
-
println( "Set(5,6,9,20,30,45) 最大元素是 : " + num.max )
打印結果為:
-
Set( 5,6,9,20,30,45) 最小元素是 : 5
-
Set( 5,6,9,20,30,45) 最大元素是 : 45
交集
你可以使用 Set.& 方法或 Set.intersect 方法來查看兩個集合的交集元素。實例如下:
-
val num1 = Set( 5,6,9,20,30,45)
-
val num2 = Set( 50,60,9,20,35,55)
-
-
// 交集
-
println( "num1.&(num2) : " + num1.&(num2) )
-
println( "num1.intersect(num2) : " + num1.intersect(num2) )
打印結果為:
-
num1.&(num2) : Set( 20, 9)
-
num1.intersect(num2) : Set( 20, 9)
Scala Set 常用方法
- 參考底部附錄:
Scala Map(映射)
- Map(映射)是一種可迭代的鍵值對(key/value)結構。
- 所有的值都可以通過鍵來獲取。
- Map 中的鍵都是唯一的。
- Map 也叫哈希表(Hash tables)。
- Map 有兩種類型,可變與不可變,區別在於可變對象可以修改它,而不可變對象不可以。
- 默認情況下 Scala 使用不可變 Map。如果你需要使用可變集合,你需要顯式的引入 import scala.collection.mutable.Map 類
- 在 Scala 中 你可以同時使用可變與不可變 Map,不可變的直接使用 Map,可變的使用 mutable.Map。
以下實例演示了不可變 Map 的應用:
-
// 空哈希表,鍵為字符串,值為整型
-
var A:Map[Char,Int] = Map()
-
-
// Map 鍵值對演示
-
val lang= Map( "Java" -> "Oracle", "C#" -> "Microsoft")
-
或者
-
val lang= Map(( "Java","Oracle"), ("C#" , "Microsoft"))
定義 Map 時,需要為鍵值對定義類型。如果需要添加 key-value 對,可以使用 + 號,如下所示:
A += ('t' ->10 )
Map 基本操作
Scala Map 幾種基本操作:keys、values、isEmpty、賦值(可變映射)
代碼示例:
Keys:
-
val lang = Map( "Java" -> "Oracle",
-
"C#" -> "Microsoft",
-
"Swift" -> "Apple")
-
Values:
-
val nums: Map[Int, Int] = Map()
-
println( "lang 中的鍵為 : " + lang.keys )
-
println( "lang 中的值為 : " + lang.values )
isEmpty:
-
println( "lang 是否為空 : " + lang.isEmpty )
-
println( "nums 是否為空 : " + nums.isEmpty )
keys和isEmpty的打印結果為:
-
lang 中的鍵為 : Set(Java, C#, Swift)
-
lang 中的值為 : MapLike(Oracle, Microsoft, Apple)
-
lang 是否為空 : false
-
nums 是否為空 : true
賦值:
-
var lang= scala.collection.mutable.Map( "Java" -> "Oracle", "C#" -> "Microsoft")
-
lang( "Java") = "sun"
-
println(lang)
打印結果為:
Map(C# -> Microsoft, Java -> sun)
Map 合並
你可以使用 ++ 運算符或 Map.++() 方法來連接兩個 Map,Map 合並時會移除重復的 key。以下演示了兩個 Map 合並的實例:
-
val lang =Map( "Java" -> "Oracle",
-
"C#" -> "Microsoft",
-
"Swift" -> "Apple")
-
val color = Map( "blue" -> "#0033FF",
-
"yellow" -> "#FFFF00",
-
"red" -> "#FF0000")
-
-
// ++ 作為運算符
-
var colors = lang ++ color
-
println( "lang ++ colors : " + colors )
-
-
// ++ 作為方法
-
colors = lang.++(colors)
-
println( "lang.++(colors)) : " + colors )
打印結果為:
-
lang ++ colors : Map(blue -> # 0033FF, C# -> Microsoft, yellow -> #FFFF00, Java -> Oracle, red -> #FF0000, Swift -> Apple)
-
lang.++(colors)) : Map(blue -> # 0033FF, C# -> Microsoft, yellow -> #FFFF00, Java -> Oracle, red -> #FF0000, Swift -> Apple)
輸出 Map 的 keys 和 values
以下通過 foreach 循環輸出 Map 中的 keys 和 values:
-
val lang =Map( "Java" -> "Oracle",
-
"C#" -> "Microsoft",
-
"Swift" -> "Apple")
-
-
lang.keys.foreach{ i =>
-
print( "Key = " + i )
-
println( "\tValue = " + lang(i) )}
打印結果為:
-
Key = JavaValue = Oracle
-
Key = C#Value = Microsoft
-
Key = SwiftValue = Apple
查看 Map 中是否存在指定的 Key
你可以使用 Map.contains 方法來查看 Map 中是否存在指定的 Key。實例如下:
-
val lang =Map( "Java" -> "Oracle",
-
"C#" -> "Microsoft",
-
"Swift" -> "Apple")
-
-
if(lang.contains("Swift")) {
-
println(lang( "Swift")+"創造了 Swift 語言")
-
}
打印結果為:
Apple創造了 Swift 語言
迭代映射
-
val lang = Map( "Java" -> "Oracle", "C#" -> "Microsoft")
-
for ((k, v) <- lang) {
-
println(k + " : " + v)
-
}
打印結果為:
-
Java : Oracle
-
C# : Microsoft
映射中K,V反轉
-
val lang = Map( "Java" -> "Oracle", "C#" -> "Microsoft")
-
val lang2 = for ((k, v) <- lang) yield (v, k)
-
for ((k, v) <- lang2) {
-
println(k + " : " + v)
-
}
打印結果為:
-
Oracle : Java
-
Microsoft : C#
已排序映射
-
//按照key的字典順序排序。
-
val scores = scala.collection.immutable.SortedMap(( "Bob", 8), ("Alice", 21), ("Fred", 17), ("Cindy", 15))
-
scores.foreach(person => println(person._1 + " : " + person._2))
打印結果為:
-
Alice : 21
-
Bob : 8
-
Cindy : 15
-
Fred : 17
Scala Map常用方法
- 參考底部附錄:
Scala Tuple(元組)
與列表一樣,元組也是不可變的,但與列表不同的是元組可以包含不同類型的元素。
元組的值是通過將單個的值包含在圓括號中構成的。例如:
-
//元組中定義了三個元素,對應的類型分別為[Int, Double, java.lang.String]。
-
val tuple1 = ( 1, 5.20, "Spark")
-
//或者
-
val tuple2 = new Tuple3(1,5.20,"Spark")
我們可以使用 tuple1._1 訪問第一個元素, tuple1._2 訪問第二個元素,如下所示:
-
//元組中定義了三個元素,對應的類型分別為[Int, Double, java.lang.String]。
-
val tuple1 = ( 1, 5.20, "Spark")
-
-
println(tuple1._1 + " : " + tuple1._2 + " : " + tuple1._3)
打印結果為:
1 : 5.2 : Spark
迭代元組
你可以使用 Tuple.productIterator() 方法來迭代輸出元組的所有元素:
-
//元組中定義了三個元素,對應的類型分別為[Int, Double, java.lang.String]。
-
val tuple1 = ( 1, 5.20, "Spark")
-
-
tuple1.productIterator.foreach{i => println( "value : " + i)}
打印結果為:
-
value : 1
-
value : 5.2
-
value : Spark
元組轉為字符串
你可以使用 Tuple.toString() 方法將元組的所有元素組合成一個字符串,實例如下:
-
//元組中定義了三個元素,對應的類型分別為[Int, Double, java.lang.String]。
-
val tuple1 = ( 1, 5.20, "Spark")
-
-
println(tuple1.toString())
打印結果為:
(1,5.2,Spark)
元素交換
你可以使用 Tuple.swap 方法來交換元組的元素。如下實例:
-
//元組中定義了兩個元素,對應的類型分別為[Int, java.lang.String]。
-
val tuple1 = ( 1, "Spark")
-
//注意:swap函數只能用於兩個元素元組
-
println(tuple1.swap)
打印結果為:
(Spark,1)
使用模式匹配獲取元組
代碼示例:
-
val t = ( 1, 3.14, "Fred")
-
val (first, second, third) = t
-
println(first + " : " + second + " : " + third)
打印結果:
1 : 3.14 : Fred
拉鏈操作
-
val num = Array( 1, 2, 3)
-
val str = Array( "first", "second", "third")
-
val com = num.zip(str). toMap
-
println(com(1)+" : "+com(2)+" : "+com(3))
打印結果為:
first : second : third
元組常用方法
- 參考底部附錄:
Scala Option(選項)
Scala Option(選項)類型用來表示一個值是可選的(有值或無值)。
Option[T] 是一個類型為 T 的可選值的容器: 如果值存在, Option[T] 就是一個 Some[T] ,如果不存在, Option[T] 就是對象 None 。
代碼示例:
-
val myMap: Map[String, String] = Map( "key1" -> "value")
-
val value1: Option[String] = myMap.get( "key1")
-
val value2: Option[String] = myMap.get( "key2")
-
-
println(value1) // Some("value1")
-
println(value2) // None
打印結果為:
-
Some(value)
-
None
Option 有兩個子類別,一個是 Some,一個是 None,當他回傳 Some 的時候,代表這個函式成功地給了你一個 String,而你可以透過 get() 這個函式拿到那個 String,如果他返回的是 None,則代表沒有字符串可以給你。
通過模式匹配來輸出匹配值。
代碼示例:
-
val lang =Map( "Java" -> "Oracle",
-
"C#" -> "Microsoft",
-
"Swift" -> "Apple")
-
-
println(show(lang.get( "Swift")))
-
println(show(lang.get( "Scala")))
-
-
def show(x:Option[String]) = x match {
-
case Some(s) => s
-
case None => "?"
-
}
打印結果為:
-
Apple
-
?
getOrElse() 方法
你可以使用 getOrElse() 方法來獲取元組中存在的元素或者使用其默認的值,實例如下:
-
val a:Option[Int] = Some( 5)
-
val b:Option[Int] = Some( 7)
-
val c:Option[Int] = None
-
-
println("a.getOrElse(0): " + a.getOrElse(0) )
-
println("b.getOrElse(1): " + b.getOrElse(1) )
-
println("c.getOrElse(10): " + c.getOrElse(10))
打印結果為:
-
a.getOrElse( 0): 5
-
b.getOrElse( 1): 7
-
c.getOrElse( 10): 10
isEmpty() 方法
你可以使用 isEmpty() 方法來檢測元組中的元素是否為 None,實例如下:
-
val a:Option[Int] = Some( 5)
-
val b:Option[Int] = None
-
println("a.isEmpty: " + a.isEmpty )
-
println("b.isEmpty: " + b.isEmpty )
打印結果為:
-
a.isEmpty: false
-
b.isEmpty: true
Scala Option 常用方法
- 參考底部附錄:
Scala Iterator(迭代器)
- Scala Iterator(迭代器)不是一個集合,它是一種用於訪問集合的方法。
- 迭代器 it 的兩個基本操作是 next 和 hasNext。
- 調用 it.next() 會返回迭代器的下一個元素,並且更新迭代器的狀態。
- 調用 it.hasNext() 用於檢測集合中是否還有元素。
讓迭代器 it 逐個返回所有元素最簡單的方法是使用 while 循環:
-
val it = Iterator( "Baidu", "Google", "Tencent", "Taobao")
-
-
while (it.hasNext){
-
println(it.next())
-
}
打印結果為:
-
Baidu
-
Google
-
Tencent
-
Taobao
查找最大與最小元素
你可以使用 it.min 和 it.max 方法從迭代器中查找最大與最小元素,實例如下:
-
val ita = Iterator( 20, 40, 2, 50, 69, 90)
-
val itb = Iterator( 20, 40, 2, 50, 69, 90)
-
-
println( "最大元素是:" + ita.max)
-
println( "最小元素是:" + itb.min)
執行結果為:
-
最大元素是: 90
-
最小元素是: 2
獲取迭代器的長度
你可以使用 it.size 或 it.length 方法來查看迭代器中的元素個數。實例如下:
-
val ita = Iterator( 20, 40, 2, 50, 69, 90)
-
val itb = Iterator( 20, 40, 2, 50, 69, 90)
-
-
println( "ita.size : " + ita.size)
-
println( "itb.length : " + itb.length)
打印結果為:
-
ita.size : 6
-
itb.length : 6
Scala Iterator 常用方法
- 參考底部附錄:
附錄:
List常用方法

隊列和棧常用操作
Scala Set 常用方法
Scala Map常用方法
元組常用方法
Scala Option 常用方法
Scala Iterator 常用方法

