Scala 中的迭代器(Iterator)
一、基本概念
迭代器是用于访问集合元素的工具,提供了一种顺序访问元素的方式,而不暴露底层集合的内部结构。
object IteratorBasics {
def main(args: Array[String]): Unit = {
// 创建迭代器
val list = List(1, 2, 3, 4, 5)
val iterator = list.iterator
println("迭代器基本操作:")
// 1. hasNext - 检查是否有下一个元素
println(s"hasNext: ${iterator.hasNext}")
// 2. next - 获取下一个元素
if (iterator.hasNext) {
println(s"第一个元素: ${iterator.next()}")
println(s"第二个元素: ${iterator.next()}")
}
// 3. 遍历剩余元素
println("剩余元素:")
while (iterator.hasNext) {
println(iterator.next())
}
// 4. 迭代器只能使用一次
println(s"\n迭代器已耗尽,hasNext: ${iterator.hasNext}")
// println(iterator.next()) // 会抛出异常
}
}
二、迭代器的主要特性
1. 一次性(一次性遍历)
object IteratorOneTime {
def main(args: Array[String]): Unit = {
val nums = Vector(10, 20, 30)
val iter = nums.iterator
println("第一次遍历:")
while (iter.hasNext) {
println(iter.next())
}
println("\n第二次遍历(迭代器已空):")
// 迭代器已耗尽,不会输出任何内容
while (iter.hasNext) {
println(iter.next()) // 不会执行
}
println("hasNext: " + iter.hasNext) // false
}
}
2. 惰性求值(Lazy Evaluation)
object IteratorLazy {
def main(args: Array[String]): Unit = {
// 创建一个大范围的迭代器(不会立即创建所有元素)
val bigIter = (1 to 1000000).iterator
// 只处理前10个元素
println("处理前10个元素:")
bigIter.take(10).foreach(println)
// 元素按需生成,节省内存
val infiniteIter = Iterator.continually(1)
println("\n无限迭代器(取前5个):")
infiniteIter.take(5).foreach(println)
}
}
3. 不存储状态
object IteratorState {
def main(args: Array[String]): Unit = {
val data = Array(1, 2, 3, 4, 5)
val iter1 = data.iterator
val iter2 = data.iterator
println("两个独立的迭代器:")
println("迭代器1: " + iter1.next()) // 1
println("迭代器2: " + iter2.next()) // 1(独立状态)
println("迭代器1: " + iter1.next()) // 2
println("迭代器2: " + iter2.next()) // 2
}
}
三、常用操作方法
1. 遍历方法
object IteratorTraversal {
def main(args: Array[String]): Unit = {
val iter = List("A", "B", "C", "D", "E").iterator
println("方法1: while循环")
while (iter.hasNext) {
println(iter.next())
}
// 重新创建迭代器
val iter2 = List(1, 2, 3, 4, 5).iterator
println("\n方法2: foreach方法")
iter2.foreach(println)
println("\n方法3: for循环")
val iter3 = List("Apple", "Banana", "Cherry").iterator
for (item <- iter3) {
println(item)
}
}
}
2. 转换操作
object IteratorTransformations {
def main(args: Array[String]): Unit = {
val numbers = (1 to 10).iterator
// map - 转换每个元素
println("Map(每个元素乘以2):")
val doubled = numbers.map(_ * 2)
println(doubled.toList) // 转换为List显示
// filter - 过滤元素
println("\nFilter(保留偶数):")
val evens = (1 to 10).iterator.filter(_ % 2 == 0)
println(evens.toList)
// flatMap - 扁平化映射
println("\nFlatMap:")
val words = List("hello", "world").iterator
val chars = words.flatMap(_.toCharArray)
println(chars.toList)
}
}
3. 查找和判断操作
object IteratorSearch {
def main(args: Array[String]): Unit = {
val data = List(15, 20, 25, 30, 35).iterator
// find - 查找第一个满足条件的元素
val found = data.find(_ > 25)
println(s"第一个大于25的元素: $found") // Some(30)
// exists - 是否存在满足条件的元素
val iter2 = List(1, 3, 5, 7, 9).iterator
val hasEven = iter2.exists(_ % 2 == 0)
println(s"是否存在偶数: $hasEven") // false
// forall - 所有元素都满足条件
val iter3 = List(2, 4, 6, 8).iterator
val allEven = iter3.forall(_ % 2 == 0)
println(s"是否都是偶数: $allEven") // true
}
}
4. 聚合操作
object IteratorAggregation {
def main(args: Array[String]): Unit = {
val numbers = (1 to 5).iterator
// foldLeft - 从左开始聚合
val sum = numbers.foldLeft(0)(_ + _)
println(s"Sum: $sum") // 15
// reduce - 缩减操作
val iter2 = List(1, 2, 3, 4, 5).iterator
val product = iter2.reduce(_ * _)
println(s"Product: $product") // 120
// count - 计数
val iter3 = List(1, 2, 3, 4, 5, 6, 7, 8).iterator
val countEven = iter3.count(_ % 2 == 0)
println(s"偶数个数: $countEven") // 4
}
}
5. 分组和切片操作
object IteratorGrouping {
def main(args: Array[String]): Unit = {
val data = (1 to 20).iterator
// take - 取前n个元素
println("前5个元素:")
println(data.take(5).toList)
// drop - 跳过前n个元素
println("\n跳过前3个后的元素:")
val iter2 = (1 to 10).iterator
println(iter2.drop(3).toList)
// slice - 获取子序列
println("\n第3到第7个元素:")
val iter3 = (1 to 10).iterator
println(iter3.slice(2, 7).toList) // 索引从0开始
// grouped - 分组
println("\n每3个一组:")
val iter4 = (1 to 10).iterator
val groups = iter4.grouped(3)
groups.foreach(group => println(group.toList))
}
}
四、创建迭代器的多种方式
object IteratorCreation {
def main(args: Array[String]): Unit = {
// 1. 从集合创建
println("1. 从集合创建:")
val fromList = List(1, 2, 3).iterator
val fromArray = Array("a", "b", "c").iterator
val fromSet = Set(1.1, 2.2, 3.3).iterator
// 2. 使用Iterator对象的方法
println("\n2. Iterator对象方法:")
// range迭代器
val rangeIter = Iterator.range(1, 10, 2) // 1,3,5,7,9
println(s"Range: ${rangeIter.toList}")
// 无限迭代器
val ones = Iterator.continually(1)
println(s"无限1(前5个): ${ones.take(5).toList}")
val increment = Iterator.from(5) // 5,6,7,8,...
println(s"从5开始(前5个): ${increment.take(5).toList}")
// 3. 迭代多个迭代器
println("\n3. 迭代多个迭代器:")
// concat - 连接迭代器
val concatIter = Iterator.concat(
List(1, 2).iterator,
List(3, 4).iterator,
List(5, 6).iterator
)
println(s"连接: ${concatIter.toList}")
// zip - 配对
val letters = List("A", "B", "C").iterator
val numbers = List(1, 2, 3).iterator
val zipped = letters.zip(numbers)
println(s"Zip: ${zipped.toList}")
// 4. 自定义迭代器
println("\n4. 自定义迭代器:")
class FibonacciIterator extends Iterator[Int] {
private var prev = 0
private var current = 1
override def hasNext: Boolean = true // 无限序列
override def next(): Int = {
val result = prev
prev = current
current = result + current
result
}
}
val fib = new FibonacciIterator
println(s"斐波那契数列(前10个): ${fib.take(10).toList}")
}
}
五、实际应用场景
1. 处理大文件
import scala.io.Source
object LargeFileProcessor {
def main(args: Array[String]): Unit = {
// 使用迭代器逐行处理大文件
val source = Source.fromFile("data/large_file.txt")
val lines = source.getLines() // 返回迭代器
println("处理大文件(取前5行):")
lines.take(5).foreach(line => {
// 处理每一行,不会一次性加载到内存
println(s"处理行: ${line.take(50)}...")
})
source.close()
}
}
2. 流式数据处理
object StreamProcessing {
def main(args: Array[String]): Unit = {
// 模拟流式数据源
def dataStream: Iterator[Int] = {
// 在实际应用中可能来自网络、传感器等
Iterator.from(1).map { n =>
Thread.sleep(100) // 模拟延迟
n * 10
}
}
println("流式数据处理:")
val processed = dataStream
.filter(_ % 20 == 0) // 过滤
.map(_ / 2) // 转换
.take(5) // 限制数量
processed.foreach(item => println(s"处理结果: $item"))
}
}
3. 分页处理
object Pagination {
def main(args: Array[String]): Unit = {
// 模拟数据库查询结果
val allData = (1 to 100).iterator
def getPage(page: Int, pageSize: Int): List[Int] = {
val start = (page - 1) * pageSize
allData.slice(start, start + pageSize).toList
}
println("第1页(每页10条):")
println(getPage(1, 10))
println("\n第2页(每页10条):")
println(getPage(2, 10))
}
}
六、注意事项和最佳实践
object IteratorBestPractices {
def main(args: Array[String]): Unit = {
// 1. 不要重复使用已耗尽的迭代器
val iter = List(1, 2, 3).iterator
iter.foreach(println) // 消耗迭代器
// val sum = iter.sum // 错误!迭代器已空
// 正确做法:重新创建
val newIter = List(1, 2, 3).iterator
println(s"重新创建的迭代器求和: ${newIter.sum}")
// 2. 避免在遍历过程中修改底层集合
val list = scala.collection.mutable.ListBuffer(1, 2, 3)
val badIter = list.iterator
// 遍历时修改集合可能导致不确定行为
// list += 4 // 危险操作!
// 3. 对于需要多次遍历的情况,使用集合而不是迭代器
val data = List(1, 2, 3, 4, 5)
// 需要多次访问时
println(s"第一次访问: ${data.sum}")
println(s"第二次访问: ${data.product}")
// 4. 使用视图(View)进行惰性链式操作
val result = (1 to 1000000).view
.filter(_ % 2 == 0)
.map(_ * 2)
.take(10)
.toList
println(s"使用视图处理: $result")
}
}
总结
迭代器的优点:
- 惰性求值,节省内存
- 适合处理大量或无限数据
- 提供丰富的操作链
- 不存储数据,只提供访问方式
迭代器的缺点:
- 只能遍历一次
- 不能随机访问
- 某些操作可能效率较低
选择建议:
- 处理大文件或流数据 → 使用迭代器
- 需要多次访问数据 → 使用集合
- 需要惰性处理链 → 使用视图或迭代器
- 需要随机访问 → 使用数组或索引序列