集合
第4章 集合
Scala集合同时支持不可变集合和可变集合,不可变集合可以安全的并发访问
不可变集合:scala.collection.immutable
可变集合:scala.collection.mutable
Scala默认采用不可变集合,对于几乎所有的集合类,Scala都同时提供了可变(mutable)和非可变(immutable)的版本。
Scala的集合有三大类:序列Seq(有序、线性)、集Set、映射Map(Key->Value),所有的集合都扩展自Iterable特质。
Iterable是指那些能生成用来访问集合中元素的 Iterator 的集合
用for(element<- array)来遍历内容
不可变集合继承层次:
Scala 数组和 Java 数组互操作,Scala Array 对应的是java 中的数组,不在Scala 集合框架层次之内
List属于Seq,因此和java的List不是同一概念。
For循环的1 to 3生成的是IndexedSeq下的Vector。
String属于IndexSeq。
Queue和Stack属于LinearSeq。
IndexSeq通过索引查找定位,速度快。
LinearSeq是线性的,有头尾概念,一般通过遍历查找。
可变集合继承层次:
可变集合更加丰富。
Seq中增加了Buffer(ArrayBuffer、ListBuffer)
其他参考不可变集合
迭代器(Iterator)
Scala 提供了外部的或内部的迭代器。内部迭代器是由集合或者迭代器的拥有者自己遍历集合;外部迭代器是由外部调用者决定迭代的结束。
Traversable特质提供了 foreach 方法,foreach 方法是个内部迭代器,接收一个函数作为参数,对集合每个元素应用该函数。
Iterable 提供了 iterator 方法,客户代码可以获取迭代器自行遍历。
内部迭代器是由集合或者迭代器的拥有者自己遍历集合
重写foreach 方法需要考虑一个问题,不管对集合做什么操作,整个文件都将会被遍历
外部迭代器:Iterable特质提供了iterator方法,iterator 方法返回了一个能用来遍历集合元素的外部迭代器
Iterable 允许只使用集合部分元素的方法,比Traversable 更早提前停止迭代,从而性能上比Traversable稍稍提高。
4.1 序列(Seq)
序列(seq)-有序、线性。
Seq 特质是通过length 和 apply 方法来定义的,Seq 代表连续有序,apply 方法能根据有序序号进行索引操作,length 方法返回集合大小。
Seq 可以用于采样数据,比如音频数据,音频数据以采样率的形式记录,其记录顺序对于数据处理是及其重要的。Seq 特质允许我们计算其滑动窗口。
val x = Seq(2, 1, 30, -20, 1, 2, 0)
LinearSeq 特质代表能够分割为头元素+尾集合的集合,这个特质通过三个“假定高效”的抽象方法来定义的: isEmpty , head , tails
注:可以用 LinearSeq 模拟栈(Stack:拿栈顶的元素很容易,但是要拿底下的就很难)
IndexedSeq 特质与Seq 特质类似,只是 IndexedSeq 随机访问更为高效
4.2 集(Set)
Set 集合类型代表一种其每个元素都是唯一的集合、至少对==方法来说是唯一。
Scala 支持三种不可变和可变Set: TreeSet, HashSet, BitSet
TreeSet用红黑树实现,红黑树是一种试图保持平衡的数据结构。
它通过检查当前节点来查找树里的元素,如果当前节点大于期望值就查找左树,如果小于期望值就查找右树,正好等于期望值就找到了正确节点。要想创建一个TreeSet,必须提供隐式的Ordering 类型以便比较大于小于。
HashSet 用树结构实现集合。最大区别在于 HashSet 用元素的Hash值决定把元素放在哪个节点上,HashSet 查找时的性能一般好于TreeSet。
4.3 映射(Map)
不可变的Map是有序的,可变的Map是无序的。
Map特质代表键值对的集合,只有有键的值才能存在。Map提供了根据键查找值的高效实现。
Map 能从键类型到值类型的偏函数(partial function)
Map 提供了当值不存在时,返回默认值的能力
->操作符用来创建对偶(键值对)
val scores = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
()表示法用来查找某个键对应的值,如果不包含请求的键将会抛出异常
val BOBsScore = scores("Bob")
contains方法:检查映射中是否有某个指定的值
val a = if (scores.contains("Bob")) scores("Bob") else 0
或
val a = scores.getOrElse("Bob", 0)
TreeMap
更新映射中的值(映射是可变的)
= 更新或添加值
scores("Bob") = 10 //如果该映射中没有该键,则添加该键;否则修改该键对应的值
+= 添加多个对偶
-+ 移除多个对偶
迭代映射
for((k, v) <- 映射) 处理k和v
for((k, v) <- 映射) yield (v, k) 交换键值的位置
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)