- 主要的集合特质
Iterable指的是那些能生成用来访问集合中所有元素的Iterator的集合:
val coll= ... //某种Iterable
val iter=coll.iterator
while (iter.hasNext)
对iter.next() 执行某种操纵
这是遍历一个集合最基本的方式。
- Seq
Seq是一个有先后次序的值的序列,比如数组或者列表。IndexedSeq允许通过整型下标快速访问任意元素。例如:ArrayBuffer是带下标的,但链表不是
- Set
Set是一组没有先后次序的值。在SortedSet中,元素以某种排序后的顺序被访问
- Map
Map是一组(键,值)对偶。SortedMap按照键的排序访问其中的实体。
Java的集合类主要由两个接口派生而出:Collection和Map。
与Java中集合的区别:
映射隶属于同一个继承层级而不是一个单独的层级关系
IndexedSeq是数组的超类,但不是列表的超类型,以便于区分
每个scala集合特质或类都有一个带有apply方法的伴生对象,这个apply方法可以用来构建该集合中的实例。例如:
Iterable(0xFF,0xFF00,0xFF0000)
Set(Color.RED,Color.GREEN,Color.BLUE)
Map(Color.RED->0xFF,Color.GREEN->0xFF00,Color.BLUE->0xFF0000)
SortedSet("Hello","World")
这样的设计叫做“统一创建原则”。
- 可变和不可变集合
不可变的集合从不改变,因此可以安全共享引用,甚至是在一个多线程的应用程序当中也没问题。例如:scala.collection.mutable.Map(可变),也有scala.collection.immutable.Map(不可变),它们有一个共有 的超类型scala.collection.Map
scala优先采用不可变集合。scala.collection包中的伴生对象产出不可变的集合。例如:scala.collection.Map("Hello"->42)是一个不可变的映射
- 序列
1) 不可变序列
- Vector
Vector是ArrayBuffer的不可变版本:一个带有下标的序列,支持快速的随机访问。向量是以树形结构的形式实现的,每个节点可以有超过32个子节点。对于一个有100万个元素的向量而言,只需要四层节点。访问这样的一个列表中的某个元素只需要4跳,而在链表中,同样操作平均需要500000跳。
- Range
Range表示一个整数序列,比如0,1,2,3,4或者10,20,30。Range对象并不存储所有值而只是起始值、结束值和增量。可以用to和until方法来构造Range对象。
2) 可变序列
这里的链表类和Java中的链表不太一样,后续具体介绍。
- 列表
在scala中,列表要么是Nil(即空表),要么是一个head元素加上一个tail,而tail又是一个列表。例如:
val digits=List(4,2)
digits.head的值是4,而digits.tail是List(2)。digits.tail.head是2,digits.tail.tail是Nil
::操作符从给定的头和尾创建一个新的列表,::是右结合。例如:
9 :: List(4,2) //List(9,4,2)
9 :: 4 :: 2 ::Nil //与上面一样,等同于9 :: (4 :: (2 :: Nil))
- 可变列表
可变的LinkedList 和不可变的List相似,只不过你可以通过对elem引用赋值来修改其头部,对next引用赋值来修改其尾部。
注意:你并不是给head和tail赋值
- 集
集是不重复元素的集合。尝试将已有元素加入没有效果。例如:
Set(2,0,1)+1 //和Set(2,0,1)一样
与列表不同,集并不保留元素插入的顺序。缺省情况下,集是以哈希集实现的,其元素根据hashCode方法的值进行组织。在哈希集中查找元素要比在数组或列表中快得多。
- 链式哈希集
链式哈希集可以记住元素被插入的顺序。它会维护一个链表来达到这个目的。例如:
val weekday=scala.collection.mutable.LinkedHashSet("Mo","Tu","We","Th","Fr")
- 已排序集
如果想按照已排序的顺序来访问集中元素,用已排序的集,已排序的集是用红黑树实现的:
scala.colletion.immutable.SortedSet(1,2,3,4,5)
注意:scala2.9中没有可变的已排序集。如果需要,可以用java.util.TreeSet
- 位集
位集是集的一种实现,以一个字位序列的方式存放非负整数。如果集中有i,则第i个字位是1。scala提供了可变和不可变的两个BitSet类。
- 用于添加或去除元素的操作符
一般,+用于将元素添加到无先后次序的集合,而+:和:+则是将元素添加到有先后次序的集合的开头或末尾。
Vector(1,2,3):+5 //Vector(1,2,3,5)
1+:Vector(1,2,3) //Vector(1,1,2,3) ,+:是右结合
这些操作符都会返回新的结合,不会修改原有的集合。而可变集合有+=操作符用于修改左侧操作元。例如:
val nums=ArrayBuffer(1,2,3)
nums +=5 //将5添加到nums
对于不可变集合,你可以在var上使用+=或者:+=,例如:
var nums=Set(1,2,3)
nums +=5 //将nums设为不可变集nums+5
var numV=Vector(1,2,3)
numV:+=5 //这里无法使用+=,因为向量没有+操作符
- 常用方法
- Iterable
- Seq
- 与Java集合的互操作
JavaConversions对象提供了用于在scala和Java集合之间来回转换的一组方法。
- 从scala集合到Java集合的转换
- 从Java集合到scala集合的转换
- 线程安全的集合
scala提供了6个特质,你可以将它们混入集合,让集合的操作变成同步的:
SynchronizedBuffer
SynchronizedMap
SynchronizedPriorityQueue
SynchronizedQueue
SynchronizedSet
SynchronizedStack
例如:
val scores=new scala.colletion.multable.HashMap[String,Int] with scala.collection.multable.SynchronizedMap[String,Int]
通常来说最好使用java.util.concurrent包中的某个类,然后将该类转换成scala集合来使用
- 并行集合
scala提供的用于操纵大型集合任务的解决方案十分优秀。这些任务通常可以很自然地并行操作。例如:
coll.par.sum //并发地对结合coll进行求和
par方法产出当前集合的一个并行实现。该实现会尽可能地并行执行集合方法。
对数组、缓冲、哈希表、平衡树而言,并行实现会直接重用底层实际集合的实现,很高效。
par方法返回的并行集合的类型为扩展自ParSeq或ParMap特质的类型,所有这些特质都是ParIterable的子类型,并不是Iterable的子类型。可以用ser方法将并行集合转换成串行的版本,也可以实现接受通用的GenIterable、GenSeq、GenSet或GenMap类型的参数方法。