转http://www.importnew.com/4543.html
Scala提供了一系列的集合类的实现。同时,它对于集合类型也进行了一些抽象。这就使得你可以操作一个集合的Foo
对象,而不用去关心这个集合是一个List
,Set
还是其他的什么。
这个网页提供了一个很好的方式来理解scala里的集合的默认实现,并且都链接到了相应的scaladoc。
基本集合类
List
标准的linked list。
1
2
|
scala> List(
1
,
2
,
3
)
res0: List[Int] = List(
1
,
2
,
3
)
|
你也可以像在函数式语言里一样把它们串接起来。
1
2
|
scala>
1
::
2
::
3
:: Nil
res1: List[Int] = List(
1
,
2
,
3
)
|
参考 API文档
Set
Set里不包含重复元素
1
2
|
scala> Set(
1
,
1
,
2
)
res2: scala.collection.immutable.Set[Int] = Set(
1
,
2
)
|
参考 API文档
Seq
Sequence都有一个预定义的顺序。
1
2
|
scala> Seq(
1
,
1
,
2
)
res3: Seq[Int] = List(
1
,
1
,
2
)
|
(注意返回的结果是一个List。Seq
是一个trait;List是它的一个实现类。Seq
对象是一个工厂对象,正如你所看到的,它会创建一个List。)
参考 API文档
Map
Map是保存键-值对的容器。
1
2
|
scala> Map(
'a'
->
1
,
'b'
->
2
)
res4: scala.collection.immutable.Map[Char,Int] = Map((a,
1
), (b,
2
))
|
参考 API文档
层级关系
上面的这些都是trait,在可变(mutable)包和不可变(immutable)包里都有对应的实现,同时也有其他特殊用途的实现。
Traversable
所有的集合都可遍历的。这个trait定义了标准函数组合器。这些组合器都是通过foreach这个方法来实现的,并且所有的集合都实现了这个方法。
参考 API文档
Iterable
这个trait有一个iterator()
方法,它返回一个可以遍历所有元素的Iterator。 参考 API文档
Seq
一组有序的元素。
参考 API文档
Set
一组没有重复元素的集合。
参考 API文档
Map
键-值对。
参考 API文档
方法
Traversable
上面所有的方法在子类中都是可用的。参数和返回值可能会改变,因为子类可以覆盖它们。
1
2
|
def head : A
def tail : Traversable[A]
|
这里我们可以定义函数组合器。
def map [B] (f: (A) => B) : CC[B]
上面的代码返回一个集合,里面的每一个元素都通过函数f
进行了转换。
def foreachU: Unit
对一个集合里的每一个元素都执行函数f
。
def find (p: (A) => Boolean) : Option[A]
它返回第一个符合断言函数的元素。
def filter (p: (A) => Boolean) : Traversable[A]
这个返回一个包含所有符合断言函数的元素的集合。
切分:
def partition (p: (A) ⇒ Boolean) : (Traversable[A], Traversable[A])
通过一个断言函数把一个集合拆成两份
def groupBy [K] (f: (A) => K) : Map[K, Traversable[A]]
转换:
有趣的是,集合之间可以相互进行转换。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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]
|
我们可以把一个Map转换成一个数组,然后得到一个键值对数组。
1
2
|
scala> Map(
1
->
2
).toArray
res41: Array[(Int, Int)] = Array((
1
,
2
))
|
Iterable
这个接口给你提供了一个迭代器iterator。
1
|
def iterator: Iterator[A]
|
Iterator提供了什么操作呢?
1
2
|
def hasNext(): Boolean
def next(): A
|
这个是非常‘Java式’的用法。在Scala中,你很少会见到使用iterator的地方,大部分的时候你看到的都是函数组合器以及for循环语句。
Set
1
2
3
|
def contains(key: A): Boolean
def +(elem: A): Set[A]
def -(elem: A): Set[A]
|
Map
一序列键值对,提供按key进行查询的操作。 可以通过给apply()方法传入一个键值对的列表来创建Map:
1
2
|
scala> Map(
"a"
->
1
,
"b"
->
2
)
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,
1
), (b,
2
))
|
或者按照下面的方式:
1
2
|
scala> Map((
"a"
,
2
), (
"b"
,
2
))
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,
2
), (b,
2
))
|
题外话
->
是什么呢?这是一个特殊的语法,它是一个返回值为元组的方法。
1
2
3
|
scala>
"a"
->
2
res0: (java.lang.String, Int) = (a,
2
)
|
记住,它只是下面这种形式的语法糖:
1
2
3
|
scala>
"a"
.->(
2
)
res1: (java.lang.String, Int) = (a,
2
)
|
你也可以通过++
来构造Map
1
2
|
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的子类,它提供有序的访问方式。 TreeMap API
Vector 支持快速查找和更新 Vector API
1
2
|
scala> IndexedSeq(
1
,
2
,
3
)
res0: IndexedSeq[Int] = Vector(
1
,
2
,
3
)
|
Range 有序的通过空格分隔的Int序列。 在之前很多用来计数的for循环经常使用它。Range API
1
2
3
4
|
scala>
for
(i <-
1
to
3
) { println(i) }
1
2
3
|
Range也支持标准的函数组合器。
1
2
|
scala> (
1
to
3
).map { i => i }
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(
1
,
2
,
3
)
|
默认实现
在trait上使用apply方法会得到该trait的一个默认实现,例如,Iterable(1,2)返回一个List作为它的默认实现。
1
2
3
|
scala> Iterable(
1
,
2
)
res0: Iterable[Int] = List(
1
,
2
)
|
Seq也是这样的,我们之前见过
1
2
3
4
5
6
7
8
9
|
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
1
2
|
scala> Set(
1
,
2
)
res31: scala.collection.immutable.Set[Int] = Set(
1
,
2
)
|
一些描述性的trait
IndexedSeq 支持对元素进行快速随机访问以及快速的length操作 API doc
LinearSeq 只对第一个和最后一个元素支持快速访问。 API doc
可变性 vs. 不可变性
不可变性
优点
- 在多线程场景下不会被改变
缺点
- 没有办法进行修改
Scala允许我们根据实际需求决定可变性,它鼓励我们只用不可变的对象,但是也不禁止我们使用具有可变性的对象。这个和var与val的场景非常相似。我们一开始都是使用val,当实际需要的时候会改成var。
可变集合
我们前面讨论的所有的类都是不可变的。我们现在来讨论一下常用的可变集合。
HashMap 定义了getOrElseUpdate
, +=
HashMap API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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和DoubleLinkedList LinkedList API, DoubleLinkedList API
PriorityQueue API doc
Stack和ArrayStack Stack API, ArrayStack API
StringBuilder 有趣的是StringBuilder是竟然一个集合 API doc
和Java进行交互
你可以通过 JavaConverters 包在Java和Scala的集合类之间进行转换. 它给常用的Java集合提供了asScala
方法,同时给常用的Scala集合提供了asJava
方法。
1
2
3
4
5
|
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)
|
双向转换:
1
2
3
4
5
6
7
|
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
|
另外,下面提供了一些单向的转换方法:
1
2
3
4
|
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
|