所有集合都扩展至特质Iterable。集合分为三类:
有先后顺序的值的集合
Array/Vector(向量/数组), Range(整数序列), 这两种集合扩展了IndexSeq特质,可以通过下标迅速的访问任意元素。
List(列表/线性表),Queue(队列),Stack(栈),Stream(流)
ArrayBuffer(数组缓冲),这种集合扩展了IndexSeq特质,可以通过下标迅速的访问任意元素。
Stack(栈),Queue(队列),Priority Queue(优先级队列),LikedList(链表),Double LikedList(双向链表)
列表是空表(Nil),或者是head+tail,这里tail又是一个列表。
val digits=List(4,2)
List(9,4,2).tail //(4,2)
//digits.head值是4,digits.tail是List(2),digits.tail.head值是2,digita.tail.tail是Nil
//可以通过::操作符从给定的头或者尾创建一个新的列表。
9::List(4,2) //就是List(9,4,2),他等同于(9::(4::(2::Nil)))
在C++或者JAVA中我们用迭代器来遍历链表,在scala中也可以这么做。但使用递归更加自然。
一个例子,计算列表之和:
def sum(lst: List[Int]): Int=
if (lst==Nil) 0 else lst.head+sum(lst.tail)
也可以使用模式匹配:
def su (lst: List[Int]): Int= lst match{
case Nil=>0
case h::t=>h+sum(t) //h是lst.head,t是lst.tail
}
这里与C语言中的链表不太相同。我们可以对elem赋值来修改头部,对next赋值来修改尾部,与List相似。
注意:在List不是在给head和tail赋值。
val lst=scala.collection.mutable.LinkedList(1,-2,-4,9)
lst.elem //1
lst.next //(-2,-4,9)
lst.next.next //(-4,9)
var cur = lst
while (cur!=Nil){
if(cur.elem<0) 0
cur=cur.next
}
另一个例子,除去每两个元素中的一个
val lst=scala.collection.mutable.LinkedList(1,-2,-4,9)
var cur = lst
while(cur!=Nil && cur.next!=Nil){
cur.next=cur.next.next
cur=cur.next
} //(1,-4)
无先后顺序、不重复的值的集合
尝试将已有的元素加入一个set是没有效果的。
集不保留元素插入的顺序,
val set1=scala.collection.mutable.Set(1,2,34,5) //(1,34,5,2)
//如果允许集合自己对元素重新排列,查找元素的速度会快得多。所以在哈希集中查找元素比在数组或列表中快得多。
val weekdays=scala.collection.mutable.LinkedHashSet("Mo","Tu","We","Th","Fr") //使用LinkedHashSet可以记住元素被插入的顺序
scala.collection.immutable.SortedSet(2,3,1,6,4) //已排序的集,(1,2,3,4,6)
注意:没有可变的已排序集。
一些方法与操作符
contains: 检查某个集是否包含给定的值
subsetOf:检查某个集当中的所有元素是否都被另一个集包含
union(++):可以理解为集合的并运算
diff(–): 可以理解为集合的差运算
+一般用于将元素添加到无先后次序的集合 (set)
:+,+: 一般用于将元素添加到有先后次序的集合的开头或结尾 (Vector,List,ArrayBuffer)
以上都不改变原有集合,而只是返回一个与原集合类型相同的新集合。+=,-=,++=,–=,改值操作符,修改左侧操作元(所以左侧需要是变量)
一组(键、值)对偶
map:将某个函数应用到集合中的每个元素并产出其结果的集合。
flatmap:如果这个函数的结果是产出一个集合而不是单一的值,仅使用map会得到一个集合包含着一些集合的结果。而使用flatmap会“消除”函数产出集合的作用,得到一个“平整的”原集合类型的集合。
collect:应用于偏函数(:只有部分输入被处理的函数),它产出被处理的所有参数的函数值的集合。"-3+4".collect{case '+'=>1;case '-' =>-1}// Vector(-1,1)
foreach:仅将函数应用到每个元素但不关心函数的值。names.foreach(println)
是二元函数,它处理集合中相邻的元素。
coll.reduceLeft(op):List(1,2,4,5).reduceLeft(_ + _)
从集合第一个元素开始,将op相继应用到相邻元素。
coll.foldLeft(init)(op):List(1,2,4,5).foldLeft(0)(_ - _)
从给定的init值开始,将op相继应用到集合的从左到右的元素。 或者协作 (init) /: coll (op) 如 ( 0 :/ List(1,2,4,5)(_ - _)
将折叠和映射操作结合在一起,得到包含有中间结果的集合。
(1 to 10).scanLeft(0)(_ + _) //Vector(0,1,3,6,10,15,21,28,...,55)
zip :将两个集合对应元素组合成一个个对偶的集合。
zipAll :可以指定较短列表的缺省值
List(1,2,3).zipAll(List(1,1),0,1) //0指当第一个集合较短时用0替代,1指当第二个集合较短时用1替代。List((1,1),(2,1),(3,1))
zipWithIndex: 返回对偶的列表。
"Scala".zipWithIndex //Vector(('S',0),('c',1),...('a',4))
"Scala".zipWithIndex.max //('l',3) 因为键l是最大的
"Scala".zipWithIndex.max._1 // l
"Scala".zipWithIndex.max._2 // 3
scala可以自然的进行并行操作,多个线程可以并发的计算不同区块,在最后这些部分结果再被汇总到一起。
par方法进行并行操作
coll.par.sum
coll.par.count(_ % 2 ==0)
注意:par方法返回的秉性集合的类型为扩展自ParSeq,ParSet,ParMap特质的类,所有这些特质都是ParIterable的子类型,而不是Iterable的子类型。
可以用ser方法将并行集合转换为串行集合。