Scala集合
scala默认采用不可变集合
一、集合概述:
1.Scala的集合有三大类:
序列Seq(有序、线性)、集合set、映射Map(Key->Value),所有的集合都扩展自Iterable特质
2.可变分类
不可变集合(可以安全的并发访问)【scala.collection.mutable】
(1)for循环的1to3生成的是IndexedSeq下的vector
(2)String属于IndexSeq
(3)Queue和Stack属于LinearSeq
(4)IndexSeq通过索引查找定位,速度快
(5)LinearSeq是线性的,有起点和终点,一般通过遍历查找
可变集合【scala.collection.immutable】
可变集合的种类非常多,在Seq中还增加了Buffer(ArrayBuffer、ListBuffer)
二、数组
1.Array是固定长度数组,ArrayBuffer是不固定长度
2.创建数组赋初值不要使用new关键字,不然是指定创建大小


3.未赋初值的数组元素都为0
4.用(i)来访问下标为i的元素
5.用for(element<-array)遍历
6.Scala Array对应的是java中的数组,不在Scala集合框架内
三、元组
1.元组是不同类型值的聚集(所以修改元组内元素的类型一定要给每个元素都指定类型)
2.创建元组
3.获取元组内元素(根据下标)
4.元组中最多只能有
22个元素
四、集合
1.主要的集合特质
集合三大类:Seq、Set、Map
2.迭代器
内部迭代器:集合或迭代器的拥有者自己遍历集合,使用foreach方法,继承Traversable特质
外部迭代器:Iterable提供了iterator方法,客户代码可以获取迭代器进行自行遍历
Iterable允许只使用集合部分元素的方法,比Traversable更早停止迭代,性能上比后者高。
使用迭代器Iterator(下图)
3.Seq特质(有序、线性)
(1)主要是通过length和apply方法定义的,apply方法根据有序序号进行索引操作,length方法返回集合大小。
(2)LinearSeq
此特质有3个方法:isEmpty、head、tail
这个特质可以看做是
头元素(head)+tail(除掉头元素以外的
集合)组成的集合(具体看下图例子)
(3)IndexSeq
与Seq特质类似,但是可以随机访问,更为高效。
4.Set特质
Set集合代表每个元素都是唯一的。
下面介绍几种set
(1)TreeSet
用红黑树实现,红黑树是一种试图保持平衡的数据结构。
它通过检查当前节点来查找树里的元素,如果当前节点大于期望值就查找左树,如果小于期望值就查找右树,正好等 于期望值就找到了正确节点。要想创建一个TreeSet,必须提供隐式的Ordering 类型以便比较大于小于。
拓展:什么是红黑树
https://www.jianshu.com/p/e136ec79235c
(2)HashSet 用
树结构实现集合。最大区别在于 HashSet 用元素的Hash值决定把元素放在哪个节 点上,HashSet 查找时的性能一般好于TreeSet。
(3)BitSet 是用Long 型的序列来实现的,BitSet 通过把其底层Long值与欲保存的整数值位置设置 为true来保存整数,BitSet经常用来在内存里跟踪和保存一大批标志位。
5.Map特质
不可变的Map是有序的,可变的Map是无序的。
Map特质代表键值对的集合,只有有键的值才能存在。Map提供了根据键查找值的高效实现。
Map的用法:
应用例子:TreeMap
五、集合的运算
1.map(元素的映射)和flatten(扁平化)
(1)map:将集合中每个元素通过制定函数映射为新的结果集合(一一对应)
①可以作计算操作
②可以进行字符串的拆解
(2).flatten:
可以通过flatmap和flatten操作将集合中每个元素通过定值函数映射为新的
扁平化结果集合。
关于flatMap和Map的对比和详细描述可以看
下面这篇博文,讲的挺形象的:
扁平化:简单直接
例子:通过flatten进行元素拼接
2.filter运算
数据筛选操作
3.fold/reduce(折叠/归约操作)
(1)reduce
二元操作对集合中的元素进行归约。
reduce包含reduceLeft和reduceRight两种操作,前者从结合的头部开始操作,后者是从尾部开始操作。
例如:求列表的和
(2)fold
折叠(fold)操作和reduce(归约)操作比较类似。fold操作需要从一个初始的“种子”值开始,并以该值作为上下文,处理集合中的每个元素。
Fold包含两个变体foldLeft和foldRight两种操作,foldLeft第一个参数为累计值,集合遍历的方向是从左到右, foldRight第二个参数为累计值,集合遍历的方向是从右到左。
4.scan(扫描操作)
扫描,即对某个集合的
所有元素做fold操作,但是会把
产生的所有中间结果放置于一个
集合中保存
5.zip(拉链操作,键和值映射起来)
六、集合分类
1.分类方式:
可变集合和不可变集合
即使计算集合和延时计算集合
顺序计算集合和并行计算集合
下面对集合分类进行举例:
2.不可变集合Vector(后面用到的比较多)
(1)Vector是由元素的
下标组成的前缀树,
带索引的不可变序列容器。
如果想要用
链式不可变集合容器,使用
List。
Vector在快速随机访问和快速随机存取方面是比较均衡的,Vectors现在是
immutable indexed sequences的默认实现。
(2)前缀树
每个节点有几个分叉,路径上的数字为几进制。
如0-7的前缀树用二叉树表示:
(3)“修改”Vector元素数据
例如:将下标0的位置修改为“new”
因为集合是不可变的,修改指定的下标值会产生新的集合,可以复用前缀树的部分数据。
3.不可变集合List
List由两个类组成,一个是代表空列表的Nil,另一个是Cons
List是个不可变的单链表,适合在头部的添加和删除操作。
List不适合中间元素的修改,如果修改则前面的元素都要重新生成,不如Vector
4.不可变集合Stream
(1)Stream是一种延迟持久(lazy persistent)的集合,也就是说
流可以延迟计算其元素的值。
Stream类似于List,但是最大的区别就是在于Stream会延迟计算。
例子:(其中zip就是链式操作,
注意warning,现在可以用LazyList来代替Stream关键字)
(2)Stream(LizyList)构造
List的构造为cons(::)
Stream的构造为#::
LazyList.empty表示空流,不是Nil
构造了有三个成员的流对象
我们可以看到:在使用到对象的时候才进行创建对象并输出相应的内容,延迟创建
5.可变集合ArrayBuffer
要使用或者创建可变集合必须使用这个包 scala.collection.mutable下的集合。
ArrayBuffer是一种可变数组,其大小与其所含的元素数不一定一致,当添加新元素到 ArrayBuffer时,如果底层数组没有满,则这个元素直接加入到数组,如果底层数组满了,则要创建 更大的数组,把元素都复制到新数组中。ArrayBuffer 对应了 java util 的ArrayList
6.视图(view)
Scala集合默认是严格和串行计算的,严格计算是指非延迟计算。
(1)集合库通过两个标准机制来把默认执行方式
转化为
并行计算
或者
延迟计算,分别是
view和par
从Seq[T]通过view方法转化为SeqView[T, ]类型,可以
实现懒操作(延迟计算)。
seqview的官方API
(2)小例子:
返回的是集合视图,由返回值可以看到,还没有计算。
等价于:
7.并行集合
Scala并行集合是操作并行化的集合。并行集合实现了一种“可拆分”的迭代器