1. 程式人生 > 程式設計 >Scala 系列(五)—— 集合型別綜述

Scala 系列(五)—— 集合型別綜述

一、集合簡介

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 包中所有集合如下圖:

https://github.com/heibaiying

3.2 scala.collection.mutable

scala.collection.mutable 包中所有集合如下圖:

https://github.com/heibaiying

3.2 scala.collection.immutable

scala.collection.immutable 包中所有集合如下圖:

https://github.com/heibaiying

三、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

參考資料

  1. docs.scala-lang.org/overviews/c…
  2. docs.scala-lang.org/overviews/c…
  3. docs.scala-lang.org/overviews/c…

更多大資料系列文章可以參見 GitHub 開源專案大資料入門指南