在集合层次结构的顶部是特质 Iterable
。此特质中的所有方法均根据抽象方法 iterator
定义,该方法逐个生成集合的元素。
def iterator: Iterator[A]
实现 Iterable
的集合类只需定义此方法;所有其他方法都可以从 Iterable
继承。
Iterable
还定义了许多具体方法,所有这些方法都列在以下表格中。这些方法属于以下类别
- 添加,
concat
,它将两个集合连接在一起,或将迭代器的所有元素追加到集合中。 - 映射操作
map
,flatMap
和collect
,它们通过对集合元素应用某些函数来生成新集合。 - 转换
to
,toList
,toVector
,toMap
,toSet
,toSeq
,toIndexedSeq
,toBuffer
,toArray
,它们将Iterable
集合转换为更具体的内容。如果目标是可变集合(to(collection.mutable.X)
,toArray
,toBuffer
),则通过复制原始元素来创建新集合。如果集合的运行时类型已与所需集合类型匹配,则所有这些转换都会返回其接收器参数不变。例如,对列表应用toList
将生成列表本身。 - 复制操作
copyToArray
。顾名思义,这会将集合元素复制到数组中。 - 大小信息操作
isEmpty
、nonEmpty
、size
、knownSize
、sizeIs
。在某些情况下,集合的元素数量可能需要遍历(例如,List
)。在其他情况下,集合可以有无限数量的元素(例如,LazyList.from(1)
)。 - 元素检索操作
head
、last
、headOption
、lastOption
和find
。这些操作选择集合的第一个或最后一个元素,或者选择第一个与条件匹配的元素。但是,请注意,并非所有集合都对“第一个”和“最后一个”的含义有明确的定义。例如,哈希集可能会根据其哈希键存储元素,而哈希键可能会在每次运行时发生变化。在这种情况下,哈希集的“第一个”元素对于程序的每次运行也可能不同。如果集合始终以相同的顺序生成其元素,则该集合为有序集合。大多数集合是有序的,但有些集合(例如哈希集)不是有序的——放弃排序会带来一些额外的效率。排序通常对于提供可重复的测试和帮助调试至关重要。这就是 Scala 集合为所有集合类型提供有序备选方案的原因。例如,HashSet
的有序备选方案是LinkedHashSet
。 - 子集合检索操作
tail
、init
、slice
、take
、drop
、takeWhile
、dropWhile
、filter
、filterNot
、withFilter
。这些操作都返回由索引范围或某个谓词标识的某个子集合。 - 细分操作
splitAt
、span
、partition
、partitionMap
、groupBy
、groupMap
、groupMapReduce
,这些操作将此集合的元素拆分为多个子集合。 - 元素测试
exists
、forall
、count
,这些操作使用给定的谓词测试集合元素。 - 折叠
foldLeft
、foldRight
、reduceLeft
、reduceRight
,这些折叠对连续的元素应用二元操作。 - 特定折叠
sum
、product
、min
、max
,这些折叠适用于特定类型(数字或可比较类型)的集合。 - 字符串 操作
mkString
和addString
提供了将集合转换为字符串的替代方法。 - 视图 操作:视图是一个延迟求值的集合。您将在 稍后 了解有关视图的更多信息。
在 Iterable
中还存在另外两种返回迭代器的函数:grouped
和 sliding
。但是,这些迭代器不会返回单个元素,而是返回原始集合中元素的整个子序列。这些子序列的最大大小作为参数提供给这些函数。grouped
函数以“分块”增量返回其元素,而 sliding
在元素上生成一个滑动“窗口”。通过查看以下 REPL 交互,可以清楚地了解两者之间的差异
scala> val xs = List(1, 2, 3, 4, 5)
xs: List[Int] = List(1, 2, 3, 4, 5)
scala> val git = xs grouped 3
git: Iterator[List[Int]] = non-empty iterator
scala> git.next()
res3: List[Int] = List(1, 2, 3)
scala> git.next()
res4: List[Int] = List(4, 5)
scala> val sit = xs sliding 3
sit: Iterator[List[Int]] = non-empty iterator
scala> sit.next()
res5: List[Int] = List(1, 2, 3)
scala> sit.next()
res6: List[Int] = List(2, 3, 4)
scala> sit.next()
res7: List[Int] = List(3, 4, 5)
Iterable 类中的操作
是什么 | 做什么 |
---|---|
抽象方法 | |
xs.iterator |
一个 iterator ,它生成 xs 中的每个元素。 |
其他迭代器 | |
xs.foreach(f) |
对 xs 的每个元素执行函数 f 。 |
xs.grouped(size) |
一个迭代器,它生成此集合的固定大小“块”。 |
xs.sliding(size) |
一个迭代器,它生成此集合中元素的固定大小滑动窗口。 |
添加 | |
xs.concat(ys) (或 xs ++ ys ) |
一个集合,它由 xs 和 ys 的元素组成。ys 是一个 IterableOnce 集合,即 Iterable 或 Iterator。 |
映射 | |
xs.map(f) |
从 xs 中的每个元素应用函数 f 获得的集合。 |
xs.flatMap(f) |
从 xs 中的每个元素应用集合值函数 f 并连接结果获得的集合。 |
xs.collect(f) |
从 xs 中的每个元素应用部分函数 f 获得的集合,其中 f 是已定义的,并收集结果。 |
转换 | |
xs.to(SortedSet) |
将集合工厂作为参数的通用转换操作。 |
xs.toList |
将集合转换为列表。 |
xs.toVector |
将集合转换为向量。 |
xs.toMap |
将键/值对集合转换为映射。如果集合没有对作为元素,则调用此操作将导致静态类型错误。 |
xs.toSet |
将集合转换为集合。 |
xs.toSeq |
将集合转换为序列。 |
xs.toIndexedSeq |
将集合转换为索引序列。 |
xs.toBuffer |
将集合转换为缓冲区。 |
xs.toArray |
将集合转换为数组。 |
复制 | |
xs copyToArray(arr, s, n) |
将集合最多 n 个元素复制到数组 arr 中,从索引 s 开始。最后两个参数是可选的。 |
大小信息 | |
xs.isEmpty |
测试集合是否为空。 |
xs.nonEmpty |
测试集合是否包含元素。 |
xs.size |
集合中的元素数量。 |
xs.knownSize |
元素数量(如果计算该数量需要常量时间),否则为 -1 。 |
xs.sizeCompare(ys) |
如果 xs 比 ys 集合短,则返回一个负值;如果 xs 比 ys 集合长,则返回一个正值;如果它们具有相同的大小,则返回 0 。即使集合是无限的,此方法也能正常工作,例如 LazyList.from(1) sizeCompare List(1, 2) 返回一个正值。 |
xs.sizeCompare(n) |
如果 xs 比 n 短,则返回一个负值;如果 xs 比 n 长,则返回一个正值;如果 xs 的大小为 n ,则返回 0 。即使集合是无限的,此方法也能正常工作,例如 LazyList.from(1) sizeCompare 42 返回一个正值。 |
xs.sizeIs < 42 , xs.sizeIs != 42 等。 |
为 xs.sizeCompare(42) < 0 、xs.sizeCompare(42) != 0 等分别提供了更方便的语法。 |
元素检索 | |
xs.head |
集合的第一个元素(或某个元素,如果未定义顺序)。 |
xs.headOption |
选项值中的 xs 的第一个元素,如果 xs 为空,则为 None。 |
xs.last |
集合的最后一个元素(或某个元素,如果未定义顺序)。 |
xs.lastOption |
选项值中的 xs 的最后一个元素,如果 xs 为空,则为 None。 |
xs.find(p) |
包含 xs 中满足 p 的第一个元素的选项,如果没有元素符合条件,则为 None 。 |
子集合 | |
xs.tail |
集合的其余部分,不包括 xs.head 。 |
xs.init |
集合的其余部分,不包括 xs.last 。 |
xs.slice(from, to) |
一个集合,包含 xs 的某个索引范围内的元素(从 from 到 to ,不包括 to )。 |
xs.take(n) |
一个集合,包含 xs 的前 n 个元素(或一些任意 n 个元素,如果未定义顺序)。 |
xs.drop(n) |
集合的其余部分,不包括 xs.take(n) 。 |
xs.takeWhile(p) |
集合中元素的最长前缀,所有元素都满足 p 。 |
xs.dropWhile(p) |
集合,不包含元素的最长前缀,所有元素都满足 p 。 |
xs.takeRight(n) |
一个集合,包含 xs 的最后 n 个元素(或一些任意 n 个元素,如果未定义顺序)。 |
xs.dropRight(n) |
集合的其余部分,不包括 xs.takeRight(n) 。 |
xs.filter(p) |
一个集合,包含满足谓词 p 的 xs 元素。 |
xs.withFilter(p) |
此集合的非严格筛选。后续对 map 、flatMap 、foreach 和 withFilter 的调用将仅应用于 xs 中条件 p 为真的那些元素。 |
xs.filterNot(p) |
由 xs 中不满足谓词 p 的那些元素组成的集合。 |
细分 | |
xs.splitAt(n) |
在某个位置拆分 xs ,得到集合对 (xs take n, xs drop n) 。 |
xs.span(p) |
根据谓词拆分 xs ,得到集合对 (xs takeWhile p, xs.dropWhile p) 。 |
xs.partition(p) |
将 xs 拆分为一对集合;一个包含满足谓词 p 的元素,另一个包含不满足谓词的元素,得到集合对 (xs filter p, xs.filterNot p) |
xs.groupBy(f) |
根据判别函数 f 将 xs 分区到一个集合映射中。 |
xs.groupMap(f)(g) |
根据判别函数 f 将 xs 分区到一个集合映射中,并对组中的每个元素应用转换函数 g 。 |
xs.groupMapReduce(f)(g)(h) |
根据判别函数 f 对 xs 进行分区,然后使用 h 函数合并将函数 g 应用到组中的每个元素的结果。 |
元素条件 | |
xs.forall(p) |
布尔值,指示谓词 p 是否对 xs 的所有元素成立。 |
xs.exists(p) |
布尔值,指示谓词 p 是否对 xs 中的某个元素成立。 |
xs.count(p) |
满足谓词 p 的 xs 中的元素数量。 |
折叠 | |
xs.foldLeft(z)(op) |
对 xs 的连续元素应用二元运算 op ,从左到右,以 z 开始。 |
xs.foldRight(z)(op) |
对 xs 的连续元素应用二元运算 op ,从右到左,以 z 结束。 |
xs.reduceLeft(op) |
对非空集合 xs 的连续元素应用二元运算 op ,从左到右。 |
xs.reduceRight(op) |
对非空集合 xs 的连续元素应用二元运算 op ,从右到左。 |
特定折叠 | |
xs.sum |
集合 xs 中的数字元素值的总和。 |
xs.product |
集合 xs 中的数字元素值的乘积。 |
xs.min |
集合 xs 中的已排序元素值的最小值。 |
xs.max |
集合 xs 中的已排序元素值的最大值。 |
xs.minOption |
与 min 类似,但如果 xs 为空,则返回 None 。 |
xs.maxOption |
与 max 类似,但如果 xs 为空,则返回 None 。 |
字符串 | |
xs.addString(b, start, sep, end) |
将字符串添加到 StringBuilder b 中,该字符串显示 xs 中的所有元素,这些元素位于分隔符 sep 之间,并用字符串 start 和 end 括起来。 start 、sep 、end 均为可选。 |
xs.mkString(start, sep, end) |
将集合转换为字符串,该字符串显示 xs 中的所有元素,这些元素位于分隔符 sep 之间,并用字符串 start 和 end 括起来。 start 、sep 、end 均为可选。 |
拉链 | |
xs.zip(ys) |
来自 xs 和 ys 的相应元素对的集合。 |
xs.zipAll(ys, x, y) |
来自 xs 和 ys 的相应元素对的集合,其中较短的序列通过附加元素 x 或 y 扩展为与较长的序列匹配。 |
xs.zipWithIndex |
来自 xs 的元素对及其索引的集合。 |
视图 | |
xs.view |
生成 xs 的视图。 |
在 Iterable
下面的继承层次结构中,你会找到三个特征:Seq、Set 和 Map。 Seq
和 Map
实现 PartialFunction 特征及其 apply
和 isDefinedAt
方法,每个方法的实现方式不同。 Set
从 SetOps 获取其 apply
方法。
对于序列,apply
是位置索引,其中元素始终从 0
开始编号。也就是说,Seq(1, 2, 3)(1)
给出 2
。对于集合,apply
是成员资格测试。例如,Set('a', 'b', 'c')('b')
给出 true
,而 Set()('a')
给出 false
。最后,对于映射,apply
是选择。例如,Map('a' -> 1, 'b' -> 10, 'c' -> 100)('b')
给出 10
。
在以下内容中,我们将更详细地解释三种集合的每一种。