《快学Scala》第十三章——集合

一.本章要点

  • 所有集合都扩展自Iterable特质;
  • 集合有三大类,分别为序列,集和映射;
  • 对于几乎所有集合类,Scala都同时提供可变和不可变的版本;
  • Scala列表要么是空的,要么拥有一头一尾,其中尾部本身是一个列表;
  • 集是无小猴次序的集合;
  • 用LinkedHashSet来保留插入顺序,或者用SortedSet来顺序进行迭代;
  • +将元素添加到无先后次序的集合中;+:和:+向前或向后追加到序列;++将两个集合串接在一起;-和--移除元素;
  • Iterable和Seq特质有数十个用于常见操作的方法。在编写冗长繁琐的循环之前,先看看这些方法是否满足你的需要;
  • 映射、折叠和拉链操作是很有用的技巧,用来将函数或操作应用到集合中的元素    

二.主要的集合特质

  Scala集合继承等级中重要的特质:

   Iterable:是指那些能生成用来访问集合中所有元素的Iterator的集合,如下:

//这是遍历一个集合最基本的方式
val coll=...//某种Iterable
val iter=coll.iterator
while(iter.hasNext)
    ....

  Seq:有先后次序的值的序列,如数组,列表等。IndexedSeq允许我们通过整型的下标访问任意元素。

  Set:一组没有先后次序的值,在sortedSet中,元素以某种排过序的顺序访问。

  Map:一组(键,值)对偶。SortedMap是按键的排序访问其中的实体。

  继承等级和Java相似,有一些改进:

    映射隶属于同一个继承等级而不是单独的层级关系;

    IndexedSeq是数组的超类型,但不是列表的超类型,以便于区分

  注:统一创建原则:Scala每个集合特质或类都有一个带有apply方法的伴生对象。

三.可变和不可变集合

  Scala有可变的也有不可变的集合,优先采用不可变集合。scala.collection包中的伴生对象产生出不可变集合,且scala包和Predef对象指向不可变特质的类型别名List,Set,Map,如Predef.Map和scala.collection.immutable.Map。  

四.序列

  

 不可变序列

  vector是ArrayBuffer的不可变版本:一个带下标的序列,支持快速的随机访问。向量是以树形结构的形式实现的。每个节点可以有不超过32个字节点。对于100万个元素,只需要访问四层节点(10^6=32^4),在链表中需要500000跳。

  Range表示一个整数序列,用to和until构造。

  

可变序列 

  栈,队列,优先级队列。。。链表有些特殊

五.列表

  在Scala中,列表要不是空表(Nil),要不是一个head元素加上一个tail,二tail又是一个列表。

  如val digits=List(4,2),digits.head为4,digits.tail是List(2),dights.tail..head=2,dights.tail.tail=Nil。

  ::操作符从给定的头和尾创建一个新的列表,且::是右结合的,如9::List(4,2)得List(9,4,2)

  遍历链表:可以使用迭代器,使用递归,模式匹配。。。

  

//递归
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)
}

六.可变列表

  可变的LinkedList和不可变的List相似,可以通过对elem引用赋值来修改其头部,对next引用赋值修改其尾部。    

七.集

  集是不重复元素的集合,是无序的(缺省情况下是哈希表实现的)。[允许集对它们从新排列,块]

  链式哈希可以记住元素插入顺序,会维护一个链表来达到这个目的(LInkedHashSet);

  按照以排序的方式访问集中的元素(SortedSet),红黑树实现。

  位集是集的一种实现,以一个字位序列的方式存放非负整。

  contains方法检查某个集是否包含给定的值,subsetOf检查某个集当中的所有元素是否被另一个集包含。union(++)、intersect(--)、diff是常用的操作,也可以写作|、&,&~ 。 

八.用于添加或去除元素的操作符

  

九.常用方法

  Iterable重要方法:

  Seq特质重要的方法:

   

 

   注:这些方法都不改变原有集合,而是返回与原有集合相同类型的集合,这叫”统一返回类型“原则。

十.将函数映射到集合

  例如map,filter等等。

  flatMap产出一个集合而不是一个值。

  collect用于偏函数——没有对所有可能输入值进行定义的函数。

十一.化简、折叠和扫描

  二元函数组合集合中的元素。如List(1,7,2,9).reduceLeft(_ - _)得((1-7)-2)-9=-17,同样Left(1,7,2,9).reduceRight(_ - _)得1-(7-(2-9))=-13,List(1,7,2,9).foldLeft(0)(_ - _)得0-1-7-2-9=-19(可以用:/来写foldLeft)。

  折叠有时候可以替换循环,如计算字母出现频率,一种是遍历这个字符串然后更新映射,另一种是将频率映射和新遇到的字母结合产生一个新的频率映射,这就是折叠,例:

(Map[Char,Int]()/:"TESthahaLYq"){
(m,c)=>m+(x->(m.getOrElse(c,0)+1))
}

十二.拉链操作

  将两个集合相互对应的元素结合在一起。如果两个集合长度不一致,zip则按短的来;zipAll会让你指出较短列表的缺省值zipWithIndex返回对偶的列表。

十三.迭代器

  可以用iterator方法从集合中获得一个迭代器(hasext(),next()等方法,遍历一次该迭代器九不能使用了),减少代价,但是迭代器很脆弱,每次对next的调用都会改变迭代器的指向。

十四.流

  流提供的是一个不可变的替代品(尾部被来计算的不可变的列表),这是懒执行的,只有当用到时才会执行。

  使用#::来构建一个流,例def numsFrom(n:BigInt):Stream[BigInt]=n #::numsFrom(n+1)。

十五.懒视图

  可以对其他集合应用view方法得到同样懒执行的效果。

十六.与Java集合的互操作

十七.线程安全的集合

十八.并行集合

十九.练习

猜你喜欢

转载自www.cnblogs.com/lyq-biu/p/11971795.html