更多集合

2018-02-24 15:49 更新

Scala提供了一套很好的集合實(shí)現(xiàn),提供了一些集合類型的抽象。這讓你的代碼可以與Foo的集合交互,而無(wú)需擔(dān)心該集合是是一個(gè)List,還是Set,或是任何你有的類型。

這里?提供了一個(gè)很好的頁(yè)面來(lái)查看各種集合的默認(rèn)實(shí)現(xiàn),并鏈接到他們的scala在線文檔。

基礎(chǔ)知識(shí)

表 List

標(biāo)準(zhǔn)的鏈表。

scala> List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)

你可以用函數(shù)式語(yǔ)言的方式連接它們。

scala> 1 :: 2 :: 3 :: Nil
res1: List[Int] = List(1, 2, 3)

參考?API文檔

集 Set

集沒(méi)有重復(fù)

scala> Set(1, 1, 2)
res2: scala.collection.immutable.Set[Int] = Set(1, 2)

參考?API文檔

序列 Seq

序列有一個(gè)給定的順序。

scala> Seq(1, 1, 2)
res3: Seq[Int] = List(1, 1, 2)

(請(qǐng)注意返回的是一個(gè)列表。因?yàn)?code>Seq是一個(gè)特質(zhì);而列表是序列的很好實(shí)現(xiàn)。如你所見(jiàn),Seq也是一個(gè)工廠單例對(duì)象,可以用來(lái)創(chuàng)建列表。)

參考?API文檔

映射 Map

映射是鍵值容器。

scala> Map('a' -> 1, 'b' -> 2)
res4: scala.collection.immutable.Map[Char,Int] = Map((a,1), (b,2))

參考?API文檔

層次結(jié)構(gòu)

下面介紹的都是特質(zhì),它們?cè)诳勺兊模╩utable)和不可變的(immutable)的包中都有特定實(shí)現(xiàn)。

Traversable

所有集合都可以被遍歷。這個(gè)特質(zhì)定義了標(biāo)準(zhǔn)函數(shù)組合子。 這些組合子根據(jù)?foreach?來(lái)寫,所有集合必須實(shí)現(xiàn)。

參考?API文檔

Iterable

iterator()方法返回一個(gè)Iterator來(lái)迭代元素。

參考?API文檔

Seq 序列

有順序的對(duì)象序列。

參考?API文檔

Set 集

沒(méi)有重復(fù)的對(duì)象集合。

參考?API文檔

Map

鍵值對(duì)。

參考?API文檔

方法

Traversable

下面所有方法在子類中都是可用的。參數(shù)和返回值的類型可能會(huì)因?yàn)樽宇惖母采w而看起來(lái)不同。

def head : A
def tail : Traversable[A]

這里是函數(shù)組合子定義的地方。

def map [B] (f: (A) => B) : CC[B]

返回每個(gè)元素都被?f?轉(zhuǎn)化的集合

def foreach[U](f: Elem => U): Unit

在集合中的每個(gè)元素上執(zhí)行?f?。

def find (p: (A) => Boolean) : Option[A]

返回匹配謂詞函數(shù)的第一個(gè)元素

def filter (p: (A) => Boolean) : Traversable[A]

返回所有匹配謂詞函數(shù)的元素集合

劃分:

def partition (p: (A) ? Boolean) : (Traversable[A], Traversable[A])

按照謂詞函數(shù)把一個(gè)集合分割成兩部分

def groupBy [K] (f: (A) => K) : Map[K, Traversable[A]]

轉(zhuǎn)換:

有趣的是,你可以轉(zhuǎn)換集合類型。

def toArray : Array[A]
def toArray [B >: A] (implicit arg0: ClassManifest[B]) : Array[B]
def toBuffer [B >: A] : Buffer[B]
def toIndexedSeq [B >: A] : IndexedSeq[B]
def toIterable : Iterable[A]
def toIterator : Iterator[A]
def toList : List[A]
def toMap [T, U] (implicit ev: <:<[A, (T, U)]) : Map[T, U]
def toSeq : Seq[A]
def toSet [B >: A] : Set[B]
def toStream : Stream[A]
def toString () : String
def toTraversable : Traversable[A]

把映射轉(zhuǎn)換為一個(gè)數(shù)組,您會(huì)得到一個(gè)鍵值對(duì)的數(shù)組。

scala> Map(1 -> 2).toArray
res41: Array[(Int, Int)] = Array((1,2))

Iterable

添加一個(gè)迭代器的訪問(wèn)。

  def iterator: Iterator[A]

一個(gè)迭代器能給你提供什么?

def hasNext(): Boolean
def next(): A

這是非常Java式的。你通常不會(huì)看到在Scala中使用迭代器,通常更容易出現(xiàn)的是函數(shù)組合器或for循環(huán)的使用。

Set

  def contains(key: A): Boolean
  def +(elem: A): Set[A]
  def -(elem: A): Set[A]

Map

通過(guò)鍵查找的鍵值對(duì)的序列。

可以像這樣將一個(gè)鍵值對(duì)列表傳入apply()

scala> Map("a" -> 1, "b" -> 2)
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2))

或者像這樣:

scala> Map(("a", 2), ("b", 2))
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,2), (b,2))
題外話

什么是->?這不是特殊的語(yǔ)法,這是一個(gè)返回元組的方法。

scala> "a" -> 2

res0: (java.lang.String, Int) = (a,2)

請(qǐng)記住,這僅僅是下面代碼的語(yǔ)法糖

scala> "a".->(2)

res1: (java.lang.String, Int) = (a,2)

您也可以使用++操作符構(gòu)建

scala> Map.empty ++ List(("a", 1), ("b", 2), ("c", 3))
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2), (c,3))

常用的子類

HashSet和HashMap?的快速查找,這些集合的最常用的形式。?HashSet?API,?HashMap?API

TreeMap?是SortedMap的一個(gè)子類,它可以讓你進(jìn)行有序訪問(wèn)。?TreeMap?API

Vector?快速隨機(jī)選擇和快速更新。?Vector?API

scala> IndexedSeq(1, 2, 3)
res0: IndexedSeq[Int] = Vector(1, 2, 3)

Range?等間隔的Int有序序列。你經(jīng)常會(huì)在for循環(huán)看到。?Range?API

scala> for (i <- 1 to 3) { println(i) }
1
2
3

Ranges支持標(biāo)準(zhǔn)的函數(shù)組合子。

scala> (1 to 3).map { i => i }
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3)

默認(rèn)實(shí)現(xiàn)

使用特質(zhì)的apply方法會(huì)給你默認(rèn)實(shí)現(xiàn)的實(shí)例,例如,Iterable(1, 2)會(huì)返回一個(gè)列表作為其默認(rèn)實(shí)現(xiàn)。

scala> Iterable(1, 2)

res0: Iterable[Int] = List(1, 2)

序列Seq也是一樣的,正如我們前面所看到的

scala> Seq(1, 2)
res3: Seq[Int] = List(1, 2)

scala> Iterable(1, 2)
res1: Iterable[Int] = List(1, 2)

scala> Sequence(1, 2)
warning: there were deprecation warnings; re-run with -deprecation for details
res2: Seq[Int] = List(1, 2)

Set

scala> Set(1, 2)
res31: scala.collection.immutable.Set[Int] = Set(1, 2)

一些描述性的特質(zhì)

IndexedSeq?快速隨機(jī)訪問(wèn)元素和一個(gè)快速的長(zhǎng)度操作。"API 文檔":http://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html

LinearSeq?通過(guò)head快速訪問(wèn)第一個(gè)元素,也有一個(gè)快速的tail操作。?API文檔

可變 vs 不可變

不可變

優(yōu)點(diǎn)

  • 在多線程中不會(huì)改變

缺點(diǎn)

  • 一點(diǎn)也不能改變

Scala允許我們是務(wù)實(shí)的,它鼓勵(lì)不變性,但不懲罰我們需要的可變性。這和var vs. val非常相似。我們總是先從val開(kāi)始并在必要時(shí)回退為var。

我們贊成使用不可改變的版本的集合,但如果性能使然,也可以切換到可變的。使用不可變集合意味著你在多線程不會(huì)意外地改變事物。

可變集合

前面討論的所有類都是不可變的。讓我們來(lái)討論常用的可變集合。

HashMap?定義了?getOrElseUpdate,?+=?HashMap?API

scala> val numbers = collection.mutable.Map(1 -> 2)
numbers: scala.collection.mutable.Map[Int,Int] = Map((1,2))

scala> numbers.get(1)
res0: Option[Int] = Some(2)

scala> numbers.getOrElseUpdate(2, 3)
res54: Int = 3

scala> numbers
res55: scala.collection.mutable.Map[Int,Int] = Map((2,3), (1,2))

scala> numbers += (4 -> 1)
res56: numbers.type = Map((2,3), (4,1), (1,2))

ListBuffer和ArrayBuffer?定義?+=?ListBuffer?API,?ArrayBuffer?API

LinkedList and DoubleLinkedList?LinkedList?API,?DoubleLinkedList?API
LinkedList和DoubleLinkedList?LinkedList?API,?DoubleLinkedList?API

PriorityQueue?API?文檔

Stack 和 ArrayStack?Stack?API,?ArrayStack?API

StringBuilder?有趣的是,StringBuilder的是一個(gè)集合。?API文檔

與Java生活

您可以通過(guò)JavaConverters package輕松地在Java和Scala的集合類型之間轉(zhuǎn)換。它用asScala?裝飾常用的Java集合以和用asJava?方法裝飾Scala集合。

   import scala.collection.JavaConverters._
   val sl = new scala.collection.mutable.ListBuffer[Int]
   val jl : java.util.List[Int] = sl.asJava
   val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
   assert(sl eq sl2)

雙向轉(zhuǎn)換:

scala.collection.Iterable <=> java.lang.Iterable
scala.collection.Iterable <=> java.util.Collection
scala.collection.Iterator <=> java.util.{ Iterator, Enumeration }
scala.collection.mutable.Buffer <=> java.util.List
scala.collection.mutable.Set <=> java.util.Set
scala.collection.mutable.Map <=> java.util.{ Map, Dictionary }
scala.collection.mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap

此外,也提供了以下單向轉(zhuǎn)換

scala.collection.Seq => java.util.List
scala.collection.mutable.Seq => java.util.List
scala.collection.Set => java.util.Set
scala.collection.Map => java.util.Map

Built at?@twitter?by?@stevej,?@marius, and?@lahosken?with much help from?@evanm,?@sprsquish,?@kevino,?@zuercher,?@timtrueman,?@wickman, and@mccv; Russian translation by?appigram; Chinese simple translation by?jasonqu; Korean translation by?enshahar;

Licensed under the?Apache License v2.0.

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)