主要的集合特质
Seq,Set,Map
Seq:一个有先后次序值的序列,比如数组或列表。IndexedSeq允许我们通过整型的下标快速地访问任意元素。举例来说,ArrayBuffer是带下标的,但链表不是。
Set:一组没有先后次序的值。在SortedSet中,元素以某种排过序的顺序被访问。
Map:一组(键,值)对偶。SortedMap按照键的排序访问其中的实体。
可变和不可变集合
不可变集合从不改变,因此你可以安全地共享其引用,甚至在一个多线程的应用程序当中也没有问题
scala.collection.mutable.Map / scala.collection.immutable.Map => scala.collection.Map(共有超类)
Scala优先采用不可变集合。scala.collection.Map("Hello"->24)是一个不可变的映射
序列
Vector是ArrayBuffer的不可变版本:一个带下标的序列,支持快速的随机访问。向量是以树形结构的形式实现的,每个节点可以有不超过32个子节点。
Range表示一个整数序列,比如0,1,2,3,4,5,Range并不存储所有值,而只有起始值、结束值和增值,可以用to和until方法来构建Range对象。
ArrayBuffer 可变序列
列表
List(9, 4, 2) = (9 :: (4 :: (2 :: Nil)))
可使用递归来遍历链表。
def sum(lst: List[Int]): Int =
if(lst == Nil) 0 else lst.head + sum(lst.tail)
def sum(lst: List[Int]): Int = lst match {
case Nil => 0
case h :: t => h + sum(t) //h是lst.head而t是lst.tail
}
可变链表
原用LinkedList,最新版本被废弃,可使用MutableList代替
def main(args: Array[String]): Unit = { val lst = scala.collection.mutable.MutableList(1, -2, 7, 9) var cur = lst while(cur != Nil) { if(cur.head < 0) cur.update(cur.head, 0) cur = cur.tail } println(lst) }
集
集是不重复元素的集合。尝试将已有元素加入没有效果。且并不保留元素插入的顺序。在缺省情况下,集是以哈希表实现的,其元素根据HashCode方法的值进行组织。
如果希望记住元素被插入的顺序,用链式哈希表,它会维护一个链表来达到这个目的;如果想按照已排序的顺序来访问集中的元素,用已排序的表(用红黑树实现):
def main(args: Array[String]): Unit = { val set1 = Set(1,2,3,4,5) val set2 = scala.collection.mutable.LinkedHashSet(5,4,3,2,1) val set3 = scala.collection.immutable.SortedSet(5,4,3,2,1) println(set1) println(set2) println(set3) }
结果:
位集(bit set)是集的一个实现,以一个字位序列的方式存放非负整数。如果集中有i,则第i个字位是1.
val digits = Set(1,7,2,9)
digits contains 0 //false
Set(1,2) subsetOf digits //true
union:|(或,也可写作++), intersect:&(且), diff:&~(异或,也可写作--)
val digits = Set(1, 7, 2, 9) val primes = Set(2, 3, 5, 7) digits union primes //Set(1,2,3,5,7,9) digits & primes //Set(2, 7) digits -- primes //Set(1, 9)
注:
- 向后(:+)或向前(+:)追加元素到序列当中。
- 添加(+)元素到无先后次序的集合中。
- 用-移除元素。
- 用++和--来批量添加或移除元素
- 对于列表,优先使用::(+:)和:::(++:)
- 改值操作有+=、++=、-=和--=
- 对于集合,更喜欢用++、&和--
- 尽量不用++:、+=:和++=:。
将函数映射到集合
def main(args: Array[String]): Unit = { val names = List("Peter", "Paul", "Jay") def ulcase(s: String) = Vector(s.toUpperCase, s.toLowerCase) val mapNames = names.map(ulcase) println(mapNames)
println(names.flatMap(ulcase))
}
输出结果为:
化简、折叠和扫描
List(1, 7, 2, 9).reduceLeft(_-_) //((1 - 7) - 2) - 9
List(1, 7, 2, 9).reduceRight(_-_) //1 - (7 - (2 - 9))
List(1, 7, 2, 9).foldLeft(0)(_-_) //0-1-7-2-9 (0 /: List(1,7,2,9))(_-_)
(1 to 10).scanLeft(0)(_+_) //Vector(0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55)
拉链操作
def main(args: Array[String]): Unit = { val prices = List(5.0, 20.0, 9.95) val quantities = List(10, 2, 1) println(prices zip quantities) val sumEach = (prices zip quantities) map {p => p._1 * p._2} val sum = sumEach.sum println(sumEach) println(sum) }
zipWithIndex方法返回对偶的列表,其中每个对偶的第二个组成部分是每个元素的下标
线程安全的集合
Scala库提供了六个特质,可以将它们混入集合,让集合的操作变成同步的:
- SynchronizedBuffer
- SynchronizedMap
- SynchronizedPriorityQueue
- SynchronizedQueue
- SynchronizedSet
- SynchronizedStack
构建步骤:
val scores = new scala.collection.mutable.HashMap[String, Int] with scala.collection.mutable.SynchronizedMap[String]
通常来说,最好使用java.util.concurrent包中的某个类