Я играю с ленивыми итераторами 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 для больших файлов.Я знаю, что вы можете столкнуться с ленивыми потоками Скалы, если будете хранить ссылки на голову потока.Поэтому в этом случае я стараюсь преобразовать результат 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)