Scala 系列(五)—— 集合型別綜述
阿新 • • 發佈:2019-12-31
一、集合簡介
Scala 中擁有多種集合型別,主要分為可變的和不可變的集合兩大類:
-
可變集合: 可以被修改。即可以更改,新增,刪除集合中的元素;
-
不可變集合類:不能被修改。對集合執行更改,新增或刪除操作都會返回一個新的集合,而不是修改原來的集合。
二、集合結構
Scala 中的大部分集合類都存在三類變體,分別位於 scala.collection
,scala.collection.immutable
,scala.collection.mutable
包中。還有部分集合類位於 scala.collection.generic
包下。
-
scala.collection.immutable
- scala.collection.mutable :包中的集合是可變的;
- scala.collection :包中的集合,既可以是可變的,也可以是不可變的。
val sortSet = scala.collection.SortedSet(1,2,3,4,5)
val mutableSet = collection.mutable.SortedSet(1,5)
val immutableSet = collection.immutable.SortedSet(1,5)
複製程式碼
如果你僅寫了 Set
而沒有加任何字首也沒有進行任何 import
,則 Scala 預設採用不可變集合類。
scala> Set(1,5)
res0: scala.collection.immutable.Set[Int] = Set(5,1,4)
複製程式碼
3.1 scala.collection
scala.collection 包中所有集合如下圖:
3.2 scala.collection.mutable
scala.collection.mutable 包中所有集合如下圖:
3.2 scala.collection.immutable
scala.collection.immutable 包中所有集合如下圖:
三、Trait Traversable
Scala 中所有集合的頂層實現是 Traversable
foreach
:
def foreach[U](f: Elem => U)
複製程式碼
實現 Traversable
的集合類只需要實現這個抽象方法,其他方法可以從 Traversable
繼承。Traversable
中的所有可用方法如下:
方法 | 作用 |
---|---|
Abstract Method: | |
xs foreach f |
為 xs 的每個元素執行函式 f |
Addition: | |
xs ++ ys |
一個包含 xs 和 ys 中所有元素的新的集合。 ys 是一個 Traversable 或 Iterator。 |
Maps: | |
xs map f |
對 xs 中每一個元素應用函式 f,並返回一個新的集合 |
xs flatMap f |
對 xs 中每一個元素應用函式 f,最後將結果合併成一個新的集合 |
xs collect f |
對 xs 中每一個元素呼叫偏函式 f,並返回一個新的集合 |
Conversions: | |
xs.toArray |
將集合轉化為一個 Array |
xs.toList |
將集合轉化為一個 List |
xs.toIterable |
將集合轉化為一個 Iterable |
xs.toSeq |
將集合轉化為一個 Seq |
xs.toIndexedSeq |
將集合轉化為一個 IndexedSeq |
xs.toStream |
將集合轉化為一個延遲計算的流 |
xs.toSet |
將集合轉化為一個 Set |
xs.toMap |
將一個(key,value)對的集合轉化為一個 Map。 如果當前集合的元素型別不是(key,value)對形式, 則報靜態型別錯誤。 |
Copying: | |
xs copyToBuffer buf |
拷貝集合中所有元素到快取 buf |
xs copyToArray(arr,s,n) |
從索引 s 開始,將集合中最多 n 個元素複製到陣列 arr。 最後兩個引數是可選的。 |
Size info: | |
xs.isEmpty |
判斷集合是否為空 |
xs.nonEmpty |
判斷集合是否包含元素 |
xs.size |
返回集合中元素的個數 |
xs.hasDefiniteSize |
如果 xs 具有有限大小,則為真。 |
Element Retrieval: | |
xs.head |
返回集合中的第一個元素(如果無序,則隨機返回) |
xs.headOption |
以 Option 的方式返回集合中的第一個元素, 如果集合為空則返回 None |
xs.last |
返回集合中的最後一個元素(如果無序,則隨機返回) |
xs.lastOption |
以 Option 的方式返回集合中的最後一個元素, 如果集合為空則返回 None |
xs find p |
以 Option 的方式返回滿足條件 p 的第一個元素, 如果都不滿足則返回 None |
Subcollection: | |
xs.tail |
除了第一個元素之外的其他元素組成的集合 |
xs.init |
除了最後一個元素之外的其他元素組成的集合 |
xs slice (from,to) |
返回給定索引範圍之內的元素組成的集合 (包含 from 位置的元素但不包含 to 位置的元素) |
xs take n |
返回 xs 的前 n 個元素組成的集合(如果無序,則返回任意 n 個元素) |
xs drop n |
返回 xs 的後 n 個元素組成的集合(如果無序,則返回任意 n 個元素) |
xs takeWhile p |
從第一個元素開始查詢滿足條件 p 的元素, 直到遇到一個不滿足條件的元素,返回所有遍歷到的值。 |
xs dropWhile p |
從第一個元素開始查詢滿足條件 p 的元素, 直到遇到一個不滿足條件的元素,返回所有未遍歷到的值。 |
xs filter p |
返回滿足條件 p 的所有元素的集合 |
xs withFilter p |
集合的非嚴格的過濾器。後續對 xs 呼叫方法 map、flatMap 以及 withFilter 都只用作於滿足條件 p 的元素,而忽略其他元素 |
xs filterNot p |
返回不滿足條件 p 的所有元素組成的集合 |
Subdivisions: | |
xs splitAt n |
在給定位置拆分集合,返回一個集合對 (xs take n,xs drop n) |
xs span p |
根據給定條件拆分集合,返回一個集合對 (xs takeWhile p,xs dropWhile p)。即遍歷元素,直到遇到第一個不符合條件的值則結束遍歷,將遍歷到的值和未遍歷到的值分別放入兩個集合返回。 |
xs partition p |
按照篩選條件對元素進行分組 |
xs groupBy f |
根據鑑別器函式 f 將 xs 劃分為集合對映 |
Element Conditions: | |
xs forall p |
判斷集合中所有的元素是否都滿足條件 p |
xs exists p |
判斷集合中是否存在一個元素滿足條件 p |
xs count p |
xs 中滿足條件 p 的元素的個數 |
Folds: | |
(z /: xs) (op) |
以 z 為初始值,從左到右對 xs 中的元素執行操作為 op 的歸約操作 |
(xs :\ z) (op) |
以 z 為初始值,從右到左對 xs 中的元素執行操作為 op 的歸約操作 |
xs.foldLeft(z) (op) |
同 (z /: xs) (op) |
xs.foldRight(z) (op) |
同 (xs :\ z) (op) |
xs reduceLeft op |
從左到右對 xs 中的元素執行操作為 op 的歸約操作 |
xs reduceRight op |
從右到左對 xs 中的元素執行操作為 op 的歸約操作 |
Specific Folds: | |
xs.sum |
累計求和 |
xs.product |
累計求積 |
xs.min |
xs 中的最小值 |
xs.max |
xs 中的最大值 |
String: | |
xs addString (b,start,sep,end) |
向 StringBuilder b 中新增一個字串, 該字串包含 xs 的所有元素。start、seq 和 end 都是可選的,seq 為分隔符,start 為開始符號,end 為結束符號。 |
xs mkString (start,seq,end) |
將集合轉化為一個字串。start、seq 和 end 都是可選的,seq 為分隔符,start 為開始符號,end 為結束符號。 |
xs.stringPrefix |
返回 xs.toString 字串開頭的集合名稱 |
Views: | |
xs.view |
生成 xs 的檢視 |
xs view (from,to) |
生成 xs 上指定索引範圍內元素的檢視 |
下面為部分方法的使用示例:
scala> List(1,5,6).collect { case i if i % 2 == 0 => i * 10 }
res0: List[Int] = List(20,40,60)
scala> List(1,6).withFilter(_ % 2 == 0).map(_ * 10)
res1: List[Int] = List(20,60)
scala> (10 /: List(1,3)) (_ + _)
res2: Int = 16
scala> List(1,-4,5) takeWhile (_ > 0)
res3: List[Int] = List(1,3)
scala> List(1,5) span (_ > 0)
res4: (List[Int],List[Int]) = (List(1,3),List(-4,5))
scala> List(1,3).mkString("[","-","]")
res5: String = [1-2-3]
複製程式碼
四、Trait Iterable
Scala 中所有的集合都直接或者間接實現了 Iterable
特質,Iterable
拓展自 Traversable
,並額外定義了部分方法:
方法 | 作用 |
---|---|
Abstract Method: | |
xs.iterator |
返回一個迭代器,用於遍歷 xs 中的元素, 與 foreach 遍歷元素的順序相同。 |
Other Iterators: | |
xs grouped size |
返回一個固定大小的迭代器 |
xs sliding size |
返回一個固定大小的滑動視窗的迭代器 |
Subcollections: | |
xs takeRigtht n |
返回 xs 中最後 n 個元素組成的集合(如果無序,則返回任意 n 個元素組成的集合) |
xs dropRight n |
返回 xs 中除了最後 n 個元素外的部分 |
Zippers: | |
xs zip ys |
返回 xs 和 ys 的對應位置上的元素對組成的集合 |
xs zipAll (ys,x,y) |
返回 xs 和 ys 的對應位置上的元素對組成的集合。其中較短的序列通過附加元素 x 或 y 來擴充套件以匹配較長的序列。 |
xs.zipWithIndex |
返回一個由 xs 中元素及其索引所組成的元素對的集合 |
Comparison: | |
xs sameElements ys |
測試 xs 和 ys 是否包含相同順序的相同元素 |
所有方法示例如下:
scala> List(1,3).iterator.reduce(_ * _ * 10)
res0: Int = 600
scala> List("a","b","c","d","e") grouped 2 foreach println
List(a,b)
List(c,d)
List(e)
scala> List("a","e") sliding 2 foreach println
List(a,b)
List(b,c)
List(c,d)
List(d,e)
scala> List("a","e").takeRight(3)
res1: List[String] = List(c,d,e)
scala> List("a","e").dropRight(3)
res2: List[String] = List(a,b)
scala> List("a","c").zip(List(1,3))
res3: List[(String,Int)] = List((a,1),(b,2),(c,3))
scala> List("a","d").zipAll(List(1,"",4)
res4: List[(String,(d,4))
scala> List("a","c").zipAll(List(1,4),"")
res5: List[(String,Any)] = List((a,"c").zipWithIndex
res6: List[(String,0),2))
scala> List("a","b") sameElements List("a","b")
res7: Boolean = true
scala> List("a","b") sameElements List("b","a")
res8: Boolean = false
複製程式碼
五、修改集合
當你想對集合新增或者刪除元素,需要根據不同的集合型別選擇不同的操作符號:
操作符 | 描述 | 集合型別 |
---|---|---|
coll(k) 即 coll.apply(k) |
獲取指定位置的元素 | Seq,Map |
coll :+ elem elem +: coll |
向集合末尾或者集合頭增加元素 | Seq |
coll + elem coll + (e1,e2,...) |
追加元素 | Seq,Map |
coll - elem coll - (e1,...) |
刪除元素 | Set,Map,ArrayBuffer |
coll ++ coll2 coll2 ++: coll |
合併集合 | Iterable |
coll -- coll2 | 移除 coll 中包含的 coll2 中的元素 | Set,ArrayBuffer |
elem :: lst lst2 :: lst |
把指定列表 (lst2) 或者元素 (elem) 新增到列表 (lst) 頭部 | List |
list ::: list2 | 合併 List | List |
set | set2 set & set2 set &~ set2 |
並集、交集、差集 | Set |
coll += elem coll += (e1,...) coll ++= coll2 coll -= elem coll -= (e1,...) coll --= coll2 |
新增或者刪除元素,並將修改後的結果賦值給集合本身 | 可變集合 |
elem +=: coll coll2 ++=: coll |
在集合頭部追加元素或集合 | ArrayBuffer |
參考資料
更多大資料系列文章可以參見 GitHub 開源專案: 大資料入門指南