【发布时间】:2012-01-28 06:21:42
【问题描述】:
我正在使用 Scala 的惰性迭代器,但遇到了一个问题。我正在尝试做的是读取一个大文件,进行转换,然后写出结果:
object FileProcessor {
def main(args: Array[String]) {
val inSource = Source.fromFile("in.txt")
val outSource = new PrintWriter("out.txt")
try {
// this "basic" lazy iterator works fine
// val iterator = inSource.getLines
// ...but this one, which incorporates my process method,
// throws OutOfMemoryExceptions
val iterator = process(inSource.getLines.toSeq).iterator
while(iterator.hasNext) outSource.println(iterator.next)
} finally {
inSource.close()
outSource.close()
}
}
// processing in this case just means upper-cases every line
private def process(contents: Seq[String]) = contents.map(_.toUpperCase)
}
所以我在大文件上遇到 OutOfMemoryException。我知道如果你保留对 Stream 头部的引用,你可能会与 Scala 的惰性 Streams 发生冲突。所以在这种情况下,我小心地将 process() 的结果转换为迭代器并丢弃它最初返回的 Seq。
有谁知道为什么这仍然会导致 O(n) 内存消耗?谢谢!
更新
针对 fge 和 huynhjl,似乎 Seq 可能是罪魁祸首,但我不知道为什么。例如,以下代码可以正常工作(而且我到处都在使用 Seq)。这段代码不会产生 OutOfMemoryException:
object FileReader {
def main(args: Array[String]) {
val inSource = Source.fromFile("in.txt")
val outSource = new PrintWriter("out.txt")
try {
writeToFile(outSource, process(inSource.getLines.toSeq))
} finally {
inSource.close()
outSource.close()
}
}
@scala.annotation.tailrec
private def writeToFile(outSource: PrintWriter, contents: Seq[String]) {
if (! contents.isEmpty) {
outSource.println(contents.head)
writeToFile(outSource, contents.tail)
}
}
private def process(contents: Seq[String]) = contents.map(_.toUpperCase)
【问题讨论】:
-
猜测:
.getLines.toSeq?
标签: scala functional-programming iterator lazy-evaluation