Scala object Iterator用法示例源码分析
用法
以下方法代码示例和结果
-
empty
: 创建一个不生成任何值的迭代器。 -
single
: 创建一个只生成单个元素的迭代器。 -
apply
: 创建一个具有给定元素的迭代器。 -
fill
: 创建一个生成某个元素计算结果的迭代器,重复 n 次。 -
tabulate
: 创建一个迭代器,它在 0 开始的整数范围上产生给定函数的值。 -
range
: 创建一个返回某个整数区间内连续值的迭代器。 -
iterate
: 创建一个无限迭代器,它重复应用给定函数到前一个结果。 -
from
: 创建一个无限长度的迭代器,它从某个起始值开始返回连续的值。 -
continually
: 创建一个无限长度的迭代器,返回计算表达式的结果。
其中,ConcatIterator
和 JoinIterator
是 Iterator
的内部类,用于实现迭代器的连接操作。通过 ++
运算符可以实现两个迭代器的连接。这些方法为 Scala 编程中处理序列提供了很大便利,可以方便地创建和操作序列。
示例
empty
:
val iterator = Iterator.empty
iterator.hasNext // false
iterator.next // 抛出 NoSuchElementException
single
:
val iterator = Iterator.single(1)
iterator.hasNext // true
iterator.next // 返回 1
iterator.hasNext // false
iterator.next // 抛出 NoSuchElementException
apply
:
val iterator = Iterator(1, 2, 3)
iterator.next // 返回 1
iterator.next // 返回 2
iterator.next // 返回 3
iterator.hasNext // false
fill
:
val iterator = Iterator.fill(5)(1)
iterator.next // 返回 1
iterator.next // 返回 1
iterator.next // 返回 1
iterator.next // 返回 1
iterator.next // 返回 1
iterator.hasNext // false
tabulate
:
val iterator = Iterator.tabulate(5)(i => i * 2)
iterator.next // 返回 0
iterator.next // 返回 2
iterator.next // 返回 4
iterator.next // 返回 6
iterator.next // 返回 8
iterator.hasNext // false
range
:
val iterator = Iterator.range(0, 5)
iterator.next // 返回 0
iterator.next // 返回 1
iterator.next // 返回 2
iterator.next // 返回 3
iterator.next // 返回 4
iterator.hasNext // false
iterate
: 这需要一个初始值和一个函数,该函数应用前一个元素来生成下一个元素。例如,我们可以创建一个迭代器,它重复应用函数f(x) = x*2
到初始值1
:
val iterator = Iterator.iterate(1)(x => x * 2)
iterator.next // 返回 1
iterator.next // 返回 2
iterator.next // 返回 4
iterator.next // 返回 8
iterator.next // 返回 16
// 可以无限迭代下去
from
: 这需要一个初始值:
val iterator = Iterator.from(1)
iterator.next // 返回 1
iterator.next // 返回 2
iterator.next // 返回 3
iterator.next // 返回 4
iterator.next // 返回 5
// 可以无限迭代下去
continually
: 这段代码创建了一个无限迭代器,每次迭代都返回下一个(1 to 5)的元素。然后使用take方法获取前10个元素。注意,这个迭代器是无限的,所以如果你尝试获取更多的元素,可能会导致程序阻塞或崩溃。
import scala.collection.mutable.Iterator
val iterator = Iterator.continually(1 to 5)
println(iterator.take(10).toList) // 输出: List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
中文源码
/** `Iterator`对象提供了创建特定迭代器的各种函数。
*
* @version 2.8
* @since 2.8
*/
object Iterator {
/** 随着`TraversableOnce`和`Iterator`的出现,拥有一个可以操作`Iterator`的构建器是很有用的,这样它们就可以与集合一起统一处理。
* 参见`scala.util.Random.shuffle`的示例。
*/
implicit def IteratorCanBuildFrom[A] = new TraversableOnce.BufferedCanBuildFrom[A, Iterator] {
def bufferToColl[B](coll: ArrayBuffer[B]) = coll.iterator
def traversableToColl[B](t: GenTraversable[B]) = t.toIterator
}
/** 不生成任何值的迭代器。 */
val empty: Iterator[Nothing] = new AbstractIterator[Nothing] {
def hasNext: Boolean = false
def next(): Nothing = throw new NoSuchElementException("next on empty iterator")
}
/** 创建一个只生成单个元素的迭代器。
* '''注意:''' 等价于Iterator(elem),但效率更高
*
* @param elem 元素
* @return 一个迭代器,在第一次调用`next`时生成`elem`,之后没有更多元素。
*/
def single[A](elem: A): Iterator[A] = new AbstractIterator[A] {
private var hasnext = true
def hasNext: Boolean = hasnext
def next(): A =
if (hasnext) { hasnext = false; elem }
else empty.next()
}
/** 创建一个具有给定元素的迭代器。
*
* @param elems 从迭代器逐个返回的元素
* @return 一个迭代器,在第一次调用`next`时生成给定的元素,之后没有更多元素。
*/
def apply[A](elems: A*): Iterator[A] = elems.iterator
/** 创建一个生成某个元素计算结果的迭代器,重复n次。
*
* @param len 迭代器返回的元素数
* @param elem 元素计算
* @return 一个迭代器,生成对`elem`进行`n`次计算的结果。
*/
def fill[A](len: Int)(elem: => A): Iterator[A] = new AbstractIterator[A] {
private var i = 0
def hasNext: Boolean = i < len
def next(): A =
if (hasNext) { i += 1; elem }
else empty.next()
}
/** 创建一个迭代器,它在0开始的整数范围上产生给定函数的值。
*
* @param end 迭代器返回的元素数
* @param f 计算元素值的函数
* @return 一个迭代器,产生值`f(0), ..., f(n -1)`。
*/
def tabulate[A](end: Int)(f: Int => A): Iterator[A] = new AbstractIterator[A] {
private var i = 0
def hasNext: Boolean = i < end
def next(): A =
if (hasNext) { val result = f(i); i += 1; result }
else empty.next()
}
/** 创建一个返回某个整数区间内连续值的迭代器。
*
* @param start 迭代器的起始值
* @param end 迭代器的结束值(不返回的第一个值)
* @return 产生值`start, start + 1, ..., end - 1`的迭代器
*/
def range(start: Int, end: Int): Iterator[Int] = range(start, end, 1)
/** 创建一个在某个整数区间内等间距值的迭代器。
*
* @param start 迭代器的起始值
* @param end 迭代器的结束值(不返回的第一个值)
* @param step 迭代器的增量(必须为正数或负数)
* @return 产生值`start, start + step, ...`直到,但不包括`end`的迭代器
*/
def range(start: Int, end: Int, step: Int): Iterator[Int] = new AbstractIterator[Int] {
if (step == 0) throw new IllegalArgumentException("zero step")
private var i = start
def hasNext: Boolean = (step <= 0 || i < end) && (step >= 0 || i > end)
def next(): Int =
if (hasNext) { val result = i; i += step; result }
else empty.next()
}
/** 创建一个无限迭代器,它重复应用给定函数到前一个结果。
*
* @param start 迭代器的起始值
* @param f 反复应用的函数
* @return 产生值`start, f(start), f(f(start)), ...`的迭代器
*/
def iterate[T](start: T)(f: T => T): Iterator[T] = new AbstractIterator[T] {
private[this] var first = true
private[this] var acc = start
def hasNext: Boolean = true
def next(): T = {
if (first) first = false
else acc = f(acc)
acc
}
}
/** 创建一个无限长度的迭代器,它从某个起始值开始返回连续的值。
* @param start 迭代器的起始值
* @return 产生值`start, start + 1, start + 2, ...`的迭代器
*/
def from(start: Int): Iterator[Int] = from(start, 1)
/** 创建一个无限长度的迭代器,以等间距返回值。
*
* @param start 迭代器的起始值
* @param step 连续值之间的增量
* @return 产生值`start, start + 1 * step, start + 2 * step, ...`的迭代器
*/
def from(start: Int, step: Int): Iterator[Int] = new AbstractIterator[Int] {
private var i = start
def hasNext: Boolean = true
def next(): Int = { val result = i; i += step; result }
}
/** 创建一个无限长度的迭代器,返回计算表达式的结果。
* 表达式在每个元素上重新计算。
*
* @param elem 元素计算
* @return 包含无限多个计算`elem`结果的迭代器。
*/
def continually[A](elem: => A): Iterator[A] = new AbstractIterator[A] {
def hasNext = true
def next = elem
}
/** 避免在应用++到大量迭代器时发生堆栈溢出,将未求值的迭代器展平成一组闭包的向量。 */
private[scala] final class ConcatIterator[+A](private[this] var current: Iterator[A], initial: Vector[() => Iterator[A]]) extends Iterator[A] {
@deprecated def this(initial: Vector[() => Iterator[A]]) = this(Iterator.empty, initial) // for binary compatibility
private[this] var queue: Vector[() => Iterator[A]] = initial
private[this] var currentHasNextChecked = false
// 将current推进到下一个非空迭代器
// 当所有迭代器耗尽时,设置current为null
@tailrec
private[this] def advance(): Boolean = {
if (queue.isEmpty) {
current = null
false
}
else {
current = queue.head()
queue = queue.tail
if (current.hasNext) {
currentHasNextChecked = true
true
} else advance()
}
}
def hasNext =
if (currentHasNextChecked) true
else if (current eq null) false
else if (current.hasNext) {
currentHasNextChecked = true
true
} else advance()
def next() =
if (hasNext) {
currentHasNextChecked = false
current.next()
} else Iterator.empty.next()
override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] =
if(current eq null) new JoinIterator(Iterator.empty, that)
else new ConcatIterator(current, queue :+ (() => that.toIterator))
}
private[scala] final class JoinIterator[+A](lhs: Iterator[A], that: => GenTraversableOnce[A]) extends Iterator[A] {
private[this] var state = 0 // 0: lhs not checked, 1: lhs has next, 2: switched to rhs
private[this] lazy val rhs: Iterator[A] = that.toIterator
def hasNext = state match {
case 0 =>
if (lhs.hasNext) {
state = 1
true
} else {
state = 2
rhs.hasNext
}
case 1 => true
case _ => rhs.hasNext
}
def next() = state match {
case 0 =>
if (lhs.hasNext) lhs.next()
else {
state = 2
rhs.next()
}
case 1 =>
state = 0
lhs.next()
case _ =>
rhs.next()
}
override def ++[B >: A](that: => GenTraversableOnce[B]) =
new ConcatIterator(this, Vector(() => that.toIterator))
}
}
import Iterator.empty
/** 迭代器是一种数据结构,允许在一个元素序列上进行迭代。
* 它具有用于检查是否有下一个可用元素的`hasNext`方法,
* 以及返回下一个元素并从迭代器中丢弃它的`next`方法。
*
* 迭代器是可变的:大多数操作都会改变其状态。尽管通常用于遍历集合的元素,
* 但也可以在没有任何集合支持的情况下使用它(请参阅伴生对象上的构造函数)。
*
* 特别重要的是注意,除非另有说明,“永远不应在调用方法后使用迭代器”。两个最重要的例外
* 也是唯一的抽象方法:`next`和`hasNext`。
*
* 这里有一个安全使用和不安全使用的示例:
*
* {{{
* def f[A](it: Iterator[A]) = {
* if (it.hasNext) { // 在`hasNext`之后安全重用"it"
* it.next // 在`next`之后安全重用"it"
* val remainder = it.drop(2) // 在此行之后再次使用"it"是*不安全的!*
* remainder.take(2) // 在此行之后再次使用"remainder"是*不安全的!*
* } else it
* }
* }}}
*
* @version 2.8
* @since 1
* @define willNotTerminateInf
* 注意:对于无限迭代器,将不会终止。
* @define mayNotTerminateInf
* 注意:对于无限迭代器,可能不会终止。
* @define preservesIterator
* 无论返回什么结果,迭代器都保持有效,可以进一步使用。
* @define consumesIterator
* 在调用此方法后,应该丢弃它被调用的迭代器。使用它是未定义的,并且可能会更改。
* @define consumesAndProducesIterator
* 在调用此方法后,应该丢弃它被调用的迭代器,并仅使用返回的迭代器。使用旧迭代器是未定义的,
* 可能会更改,并且可能会导致新迭代器的更改。
* @define consumesTwoAndProducesOneIterator
* 在调用此方法后,应该丢弃它被调用的迭代器,以及作为参数传递的迭代器,并仅使用返回的迭代器。
* 使用旧迭代器是未定义的,可能会更改,并且可能会导致新迭代器的更改。
* @define consumesOneAndProducesTwoIterators
* 在调用此方法后,应该丢弃它被调用的迭代器,并仅使用返回的迭代器。使用旧迭代器是未定义的,
* 可能会更改,并且可能会导致新迭代器的更改。
* @define consumesTwoIterators
* 在调用此方法后,应该丢弃它被调用的迭代器,以及作为参数传递的迭代器。使用旧迭代器是未定义的,并且可能会更改。
*/
trait Iterator[+A] extends TraversableOnce[A] {
self =>
def seq: Iterator[A] = this
/** 测试此迭代器是否可以提供另一个元素。
*
* @return 如果对`next`的随后调用将产生一个元素,则返回`true`,否则返回`false`。
* @note 重用:$preservesIterator
*/
def hasNext: Boolean
/** 生成此迭代器的下一个元素。
*
* @return 此迭代器的下一个元素,如果`hasNext`为`true`,则行为未定义。
* @note 重用:$preservesIterator
*/
def next(): A
/** 测试此迭代器是否为空。
*
* @return 如果`hasNext`为`false`,则返回`true`,否则返回`false`。
* @note 重用:$preservesIterator
*/
def isEmpty: Boolean = !hasNext
/** 测试此迭代器是否可多次遍历。
*
* @return `false`
* @note 重用:$preservesIterator
*/
def isTraversableAgain = false
/** 测试此迭代器是否具有已知大小。
*
* @return 对于空迭代器返回`true`,否则返回`false`。
* @note 重用:$preservesIterator
*/
def hasDefiniteSize = isEmpty
/** 选择此迭代器的前n个值。
*
* @param n 要获取的值的数量
* @return 一个仅生成此迭代器的前`n`个值的迭代器,如果它产生的值少于`n`个,则返回整个迭代器。
* @note 重用:$consumesAndProducesIterator
*/
def take(n: Int): Iterator[A] = slice(0, n)
/**
* 从当前迭代器中跳过前n个元素,或者跳过整个迭代器的长度,取两者较小值。
*
* @param n 要跳过的元素个数
* @return 一个迭代器,产生当前迭代器的所有值,但省略前n个值。
* @note 重用:$consumesAndProducesIterator
*/
def drop(n: Int): Iterator[A] = {
var j = 0
while (j < n && hasNext) {
next()
j += 1
}
this
}
/**
* 创建一个迭代器,返回此迭代器生成的值的一个区间。
*
* @param from 该迭代器中作为切片一部分的第一个元素的索引。
* @param until 切片之后的第一个元素的索引。
* @return 一个迭代器,它通过使用`drop`方法将此迭代器前进到前`from`个元素,然后使用`take`方法来获取`until - from`个元素。
* @note 重用:$consumesAndProducesIterator
*/
def slice(from: Int, until: Int): Iterator[A] = {
val lo = from max 0
var toDrop = lo
while (toDrop > 0 && self.hasNext) {
self.next()
toDrop -= 1
}
new AbstractIterator[A] {
private var remaining = until - lo
def hasNext = remaining > 0 && self.hasNext
def next(): A =
if (remaining > 0) {
remaining -= 1
self.next()
}
else empty.next()
}
}
/**
* 使用转换函数将此迭代器产生的所有值映射到新值,创建一个新的迭代器。
*
* @param f 转换函数
* @return 一个新的迭代器,它通过将该迭代器生成的每个值应用函数`f`来转换。
* @note 重用:$consumesAndProducesIterator
*/
def map[B](f: A => B): Iterator[B] = new AbstractIterator[B] {
def hasNext = self.hasNext
def next() = f(self.next())
}
/**
* 将此迭代器与另一个迭代器连接起来。
*
* @param that 另一个迭代器
* @return 一个新的迭代器,首先产生此迭代器生成的值,然后产生迭代器`that`生成的值。
* @note 重用:$consumesTwoAndProducesOneIterator
*
* @usecase def ++(that: => Iterator[A]): Iterator[A]
* @inheritdoc
*/
def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new Iterator.JoinIterator(self, that)
/**
* 创建一个新的迭代器,通过对此迭代器生成的每个值应用函数`f`来转换所有值,并连接结果。
*
* @param f 对每个元素应用的函数。
* @return 应用给定的返回迭代器的函数`f`到此迭代器生成的每个值,并连接结果的迭代器。
* @note 重用:$consumesAndProducesIterator
*/
def flatMap[B](f: A => GenTraversableOnce[B]): Iterator[B] = new AbstractIterator[B] {
private var cur: Iterator[B] = empty
private def nextCur() { cur = f(self.next()).toIterator }
def hasNext: Boolean = {
// 等价于 cur.hasNext || self.hasNext && { nextCur(); hasNext }
// 但是字节码更短(更好的JVM内联!)
while (!cur.hasNext) {
if (!self.hasNext) return false
nextCur()
}
true
}
def next(): B = (if (hasNext) cur else empty).next()
}
/**
* 返回满足谓词`p`的此迭代器的所有元素的迭代器。
* 元素的顺序保持不变。
*
* @param p 用于测试值的谓词。
* @return 一个迭代器,它生成此迭代器中满足谓词`p`的那些值。
* @note 重用:$consumesAndProducesIterator
*/
def filter(p: A => Boolean): Iterator[A] = new AbstractIterator[A] {
// TODO 2.12 - 创建一个完整的FilterImpl,将反向p的意义
private var hd: A = _
private var hdDefined: Boolean = false
def hasNext: Boolean = hdDefined || {
do {
if (!self.hasNext) return false
hd = self.next()
} while (!p(hd))
hdDefined = true
true
}
def next() = if (hasNext) { hdDefined = false; hd } else empty.next()
}
/**
* 测试此迭代器的每个元素是否通过满足测试谓词来与另一个集合的对应元素相关。
*
* @param that 其他集合
* @param p 调用`p(x, y)`为true来关联两个集合中的元素x和y的测试谓词
* @tparam B `that`的元素类型
* @return 如果两个集合具有相同的长度,并且对于所有对应的元素x和y,`p(x, y)`为true,则返回`true`,否则返回`false`
*/
def corresponds[B](that: GenTraversableOnce[B])(p: (A, B) => Boolean): Boolean = {
val that0 = that.toIterator
while (hasNext && that0.hasNext)
if (!p(next(), that0.next())) return false
hasNext == that0.hasNext
}
/**
* 创建一个迭代器,该迭代器产生满足谓词`p`的此迭代器的所有元素。
* 元素的顺序保持不变。
*
* '''注意:''' `withFilter`与迭代器上的`filter`方法相同。它存在的目的是使带有过滤器的for表达式适用于迭代器。
*
* @param p 用于测试值的谓词。
* @return 一个迭代器,它生成此迭代器中满足谓词`p`的那些值。
* @note 重用:$consumesAndProducesIterator
*/
def withFilter(p: A => Boolean): Iterator[A] = filter(p)
/**
* 创建一个迭代器,该迭代器产生此迭代器中不满足谓词`p`的所有元素。
*
* @param p 用于测试值的谓词。
* @return 一个迭代器,它生成此迭代器中不满足谓词`p`的那些值。
* @note 重用:$consumesAndProducesIterator
*/
def filterNot(p: A => Boolean): Iterator[A] = filter(!p(_))
/**
* 使用部分函数将此迭代器产生的所有值转换为新值,并删除未定义部分函数的那些值。
*
* @param pf 对迭代器进行过滤和映射的部分函数。
* @return 一个新的迭代器,它产生此迭代器生成的每个值`x`,其中`pf`被定义并映射到图像`pf(x)`。
* @note 重用:$consumesAndProducesIterator
*/
@migration("`collect` has changed. The previous behavior can be reproduced with `toSeq`.", "2.8.0")
def collect[B](pf: PartialFunction[A, B]): Iterator[B] = new AbstractIterator[B] {
// 为了避免额外的缓冲层包装,手动缓冲
private[this] var hd: A = _
// 状态机,用于跟踪我们所处的位置
// Seek = 0; Found = 1; Empty = -1
// 不在vals中,因为scalac不会使它们静态化(@inline def仅适用于-optimize)
// 非常小心保持注释和数字同步!
private[this] var status = 0/*Seek*/
def hasNext = {
while (status == 0/*Seek*/) {
if (self.hasNext) {
hd = self.next()
if (pf.isDefinedAt(hd)) status = 1/*Found*/
}
else status = -1/*Empty*/
}
status == 1/*Found*/
}
def next() = if (hasNext) { status = 0/*Seek*/; pf(hd) } else Iterator.empty.next()
}
/**
* 生成包含从左到右应用运算符的累积结果的集合。
*
* $willNotTerminateInf
* $orderDependent
*
* @tparam B 结果集合中元素的类型
* @param z 初始值
* @param op 应用于中间结果和元素的二元运算符
* @return 具有中间结果的迭代器
* @note 重用:$consumesAndProducesIterator
*/
def scanLeft[B](z: B)(op: (B, A) => B): Iterator[B] = new AbstractIterator[B] {
var hasNext = true
var elem = z
def next() = if (hasNext) {
val res = elem
if (self.hasNext) elem = op(elem, self.next())
else hasNext = false
res
} else Iterator.empty.next()
}
/**
* 生成包含从右到左应用运算符的累积结果的集合。
* 集合的头是最后一个累积结果。
*
* $willNotTerminateInf
* $orderDependent
*
* @tparam B 结果集合中元素的类型
* @param z 初始值
* @param op 应用于中间结果和元素的二元运算符
* @return 具有中间结果的迭代器
* @example {{{
* Iterator(1, 2, 3, 4).scanRight(0)(_ + _).toList == List(10, 9, 7, 4, 0)
* }}}
* @note 重用:$consumesAndProducesIterator
*/
def scanRight[B](z: B)(op: (A, B) => B): Iterator[B] = toBuffer.scanRight(z)(op).iterator
/**
* 获取由满足谓词`p`的最长前缀元素组成的此迭代器。
*
* @param p 测试元素的谓词。
* @return 一个迭代器,返回此迭代器生成的值,直到此迭代器产生不满足谓词`p`的值为止。
* @note 重用:$consumesAndProducesIterator
*/
def takeWhile(p: A => Boolean): Iterator[A] = new AbstractIterator[A] {
private var hd: A = _
private var hdDefined: Boolean = false
private var tail: Iterator[A] = self
def hasNext = hdDefined || tail.hasNext && {
hd = tail.next()
if (p(hd)) hdDefined = true
else tail = Iterator.empty
hdDefined
}
def next() = if (hasNext) { hdDefined = false; hd } else empty.next()
}
/**
* 将此迭代器根据谓词进行分区。
*
* @param p 用于分区的谓词
* @return 一个迭代器对:满足谓词`p`的迭代器和不满足谓词`p`的迭代器。
* 结果迭代器中元素的相对顺序与原始迭代器中的顺序相同。
* @note 重用:$consumesOneAndProducesTwoIterators
*/
def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
val self = buffered
class PartitionIterator(p: A => Boolean) extends AbstractIterator[A] {
var other: PartitionIterator = _
val lookahead = new mutable.Queue[A]
def skip() =
while (self.hasNext && !p(self.head)) {
other.lookahead += self.next
}
def hasNext = !lookahead.isEmpty || { skip(); self.hasNext }
def next() = if (!lookahead.isEmpty) lookahead.dequeue()
else { skip(); self.next() }
}
val l = new PartitionIterator(p)
val r = new PartitionIterator(!p(_))
l.other = r
r.other = l
(l, r)
}
的顺序相同。
* @note 重用:$consumesOneAndProducesTwoIterators
*/
def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = {
val self = buffered
class PartitionIterator(p: A => Boolean) extends AbstractIterator[A] {
var other: PartitionIterator = _
val lookahead = new mutable.Queue[A]
def skip() =
while (self.hasNext && !p(self.head)) {
other.lookahead += self.next
}
def hasNext = !lookahead.isEmpty || { skip(); self.hasNext }
def next() = if (!lookahead.isEmpty) lookahead.dequeue()
else { skip(); self.next() }
}
val l = new PartitionIterator(p)
val r = new PartitionIterator(!p(_))
l.other = r
r.other = l
(l, r)
}