迭代器

61 阅读6分钟

一、迭代器(Iterator)的定义

在 Scala 中,迭代器(Iterator)  是一种用于遍历集合(如 List、Set、Map 等)元素的对象,它提供了一种按需访问集合元素的方式 ——不会一次性加载集合所有元素到内存,而是通过指针记录当前遍历位置,每次仅获取下一个元素,遍历完成后迭代器不可复用。

迭代器的核心特征:

  • 是 “单向” 的:只能从前往后遍历,无法回退;
  • 是 “惰性” 的:仅在调用next()时才获取下一个元素;
  • 遍历后失效:迭代器遍历完所有元素后,再次调用hasNext()会返回falsenext()会抛出NoSuchElementException

Scala 中获取迭代器的方式:集合.iterator(如List(1,2,3).iterator)。

二、迭代器的基本使用

迭代器的核心操作依赖两个方法:hasNext()(判断是否还有下一个元素)和next()(获取下一个元素),常见使用方式有 3 种:

1. 基础 while 循环(最底层用法)

scala

// 1. 创建迭代器
val it = List(1,2,3,4,5).iterator

// 2. 遍历:hasNext()判断是否有元素,next()获取元素
while (it.hasNext) {
  println(it.next()) // 依次输出1、2、3、4、5
}


2. foreach 遍历(简洁写法)

迭代器支持foreach方法,底层仍基于hasNext()next()实现:

scala

val it = List("a", "b", "c").iterator
it.foreach(ele => println(ele)) // 依次输出a、b、c

3. 模式匹配 / 解构遍历

结合 Scala 模式匹配简化元素提取:

scala

val it = List("a", "b", "c").iterator 
it.foreach(ele => println(ele)) // 依次输出a、b、c

注意:迭代器不可复用

scala

val it = List(1,2).iterator
it.next() // 获取1
it.next() // 获取2
it.hasNext // false,迭代器已耗尽
it.next()  // 抛出NoSuchElementException

scala

一、Scala 迭代器(Iterator)的定义

Scala 中的Iterator是一个单向、惰性的遍历工具,用于逐个访问集合(如 List、Set、Map 等)中的元素,它本身不存储数据,仅提供访问集合元素的接口。

  • 迭代器有两个核心状态:hasNext(判断是否还有下一个元素)和next(获取下一个元素并移动指针)。
  • 特性:单向不可逆(一旦调用next移动指针,无法回退)、惰性计算(仅在调用next时才获取元素,而非提前加载所有元素)。

语法定义:

scala

val iter: Iterator[T] = 集合.iterator  // T为集合元素类型

二、Scala 迭代器的基本使用

迭代器的核心操作围绕hasNextnext展开,常见使用方式有 3 种:

1. 基础循环(while)

最原生的用法,通过hasNext判断、next获取元素:

scala

// 1. 创建迭代器
val list = List(1,2,3,4,5)
val iter = list.iterator

// 2. 遍历迭代器
while (iter.hasNext) {
  val elem = iter.next()
  println(elem) // 输出:1 2 3 4 5
}

2. for 循环遍历

Scala 语法糖,底层仍调用hasNextnext

scala

val iter = List("a", "b", "c").iterator
for (elem <- iter) {
  println(elem) // 输出:a b c
}

3. 转换为集合(慎用,会消耗迭代器)

迭代器是一次性的,转换为集合后迭代器会被耗尽:

scala

val iter = List(10,20,30).iterator
val newList = iter.toList // 迭代器耗尽,后续无法再调用next
println(newList) // 输出:List(10,20,30)

注意:迭代器耗尽后不可复用

scala

val iter = List(1,2).iterator
iter.next() // 获取1
iter.next() // 获取2
iter.hasNext // false,迭代器已耗尽
iter.next()  // 抛出NoSuchElementException

三、Scala 迭代器的优点

  1. 惰性加载,节省内存迭代器不提前加载所有元素到内存,仅在调用next时才获取元素,适合处理超大集合(如 GB 级数据),避免一次性加载所有数据导致 OOM。
  2. 统一的遍历接口所有 Scala 集合(List/Set/Map/Array 等)都实现了iterator方法,迭代器提供了统一的遍历方式,无需关注集合底层实现。
  3. 减少中间对象创建迭代器的方法(如mapfilter)返回的仍是迭代器,而非新集合,避免频繁创建中间集合,提升性能。
  4. 适配流式处理结合惰性特性,迭代器天然适配 “按需处理” 的场景(如大数据流式计算),仅处理当前需要的元素。

四、Scala 迭代器的常见方法

Scala 迭代器提供了丰富的方法,可分为基础方法转换方法聚合方法三类:

类别方法名作用说明
基础方法hasNext: Boolean判断迭代器是否还有下一个元素
next(): T获取下一个元素,无元素时抛出NoSuchElementException
reset()部分迭代器支持重置(如BufferedIterator),恢复到初始状态(慎用,非所有迭代器支持)
转换方法map(f: T => S): Iterator[S]对每个元素应用函数f,返回新迭代器(惰性)
filter(p: T => Boolean): Iterator[T]过滤出满足条件p的元素,返回新迭代器(惰性)
take(n: Int): Iterator[T]取前n个元素,返回新迭代器
drop(n: Int): Iterator[T]跳过前n个元素,返回新迭代器
zip(that: Iterator[S]): Iterator[(T, S)]与另一个迭代器 “拉链” 配对,返回元组迭代器(以短的迭代器长度为准)
flatMap(f: T => TraversableOnce[S]): Iterator[S]扁平化映射,拆解嵌套集合
聚合方法foreach(f: T => Unit): Unit遍历每个元素并执行函数f(无返回值)
foldLeft(init: S)(f: (S, T) => S): S从左到右聚合元素,初始值为init
sum/max/min求和 / 最大值 / 最小值(仅适用于数值类型迭代器)
toList/toSet/toMap转换为对应集合(耗尽迭代器)
其他方法isEmpty: Boolean判断迭代器是否为空(等效于!hasNext
exists(p: T => Boolean): Boolean判断是否存在满足条件p的元素
forall(p: T => Boolean): Boolean判断所有元素是否都满足条件p

常见方法示例

scala

val iter = List(1,2,3,4,5).iterator

// 1. take/drop
val takeIter = iter.take(2) // 取前2个元素:1,2
takeIter.foreach(println)  // 输出:1 2

// 重置迭代器(重新创建)
val iter2 = List(1,2,3,4,5).iterator
val dropIter = iter2.drop(2) // 跳过前2个:3,4,5
dropIter.foreach(println)    // 输出:3 4 5

// 2. zip
val iter3 = List(1,2,3).iterator
val strIter = List("a","b").iterator
val zipIter = iter3.zip(strIter)
zipIter.foreach(println) // 输出:(1,a) (2,b)

// 3. map + filter
val iter4 = List(1,2,3,4,5).iterator
val newIter = iter4.filter(_ % 2 == 0).map(_ * 2)
newIter.foreach(println) // 输出:4 8

// 4. foldLeft聚合
val iter5 = List(1,2,3).iterator
val sum = iter5.foldLeft(0)(_ + _)
println(sum) // 输出:6

关键注意点

  1. 迭代器是一次性的:一旦遍历(或转换为集合),迭代器会被耗尽,无法再次使用;

  2. 惰性特性:map/filter等转换方法仅生成 “待执行” 的迭代器,直到调用next/foreach才真正计算;

  3. 线程不安全:迭代器不支持多线程并发访问,需手动加锁或使用线程安全的迭代器实现。