快学Scala(13)--集合

Posted on 2017-04-05 21:21  paulingzhou  阅读(438)  评论(0编辑  收藏  举报

主要的集合特质

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.headt是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)

  注:

  1. 向后(:+)或向前(+:)追加元素到序列当中。
  2. 添加(+)元素到无先后次序的集合中。
  3. 用-移除元素。
  4. 用++和--来批量添加或移除元素
  5. 对于列表,优先使用::(+:)和:::(++:)
  6. 改值操作有+=、++=、-=和--=
  7. 对于集合,更喜欢用++、&和--
  8. 尽量不用++:、+=:和++=:。

将函数映射到集合

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包中的某个类