Scala集合

本文深入讲解Scala中的集合概念,包括不可变与可变集合的区别,集合的三大类:Seq、Set、Map,以及数组、元组、迭代器的使用。探讨了集合的运算,如map、filter、fold/reduce,并介绍了集合的分类方式,如顺序计算集合和并行计算集合,为读者提供了全面的Scala集合使用指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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并行集合是操作并行化的集合。并行集合实现了一种“可拆分”的迭代器

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值