好的,我正在使用dbpedia处理英语维基百科转储。到目前为止,他们的实现扩展了Traversable
并提供了foreach
来覆盖转储。但是,我希望有map
,grouped
等典型的地图操作。以下是我打开的问题:https://github.com/dbpedia/extraction-framework/issues/140
所以我添加了一个getter来接收一个iterable和一个迭代器。现在有趣的部分:
source.iterable
.map(parser)
.zipWithIndex
.map { case(page: PageMode, i: Int) =>
if(i%1000 == 0){println(i)}
(...)
}
.grouped(2000)
上面的代码内存不足。但是:
source.iterator
.map(parser)
.zipWithIndex
.map { case(page: PageNode, i: Int) =>
if(i%1000 == 0){println(i)}
(...)
}
.grouped(2000)
此代码会立即返回。
在我看来,第一个示例在内存耗尽时完全运行代码,因为它试图将转储存储在内存中。后者没有。但是,后者在Seq上返回迭代器而不是在迭代器上返回迭代器。
这是一个可迭代类的预期还是我做错了什么。我希望它们都能立即返回并且只在迭代后消耗内存。
谢谢你的帮助! 卡斯滕
答案 0 :(得分:3)
默认情况下,Scala中的所有集合(流和视图除外)都是严格的,因此每个函数都集合在一起:
pages
.map(parser)
.zipWithIndex
.map { partialFunction }
将返回新集合。您可以使用视图避免某些中间结果,然后将其强制恢复为您的集合类型:
pages.view
.map(parser)
.zipWithIndex
.map { partialFunction }
.force
了解更多详情http://www.scala-lang.org/docu/files/collections-api/collections_42.html
答案 1 :(得分:0)
调用iterable
会返回Iterable
,这只是指具有iterator
方法的集合。所以:
source.iterable
返回一个可迭代的集合,可能会也可能不会完全保留在内存中map
,zipWithIndex
,map
和grouped
都生成了中间集合另一方面呼叫iterator
:
source.iterator
会针对可能会或可能不会完全记忆的内容返回Iterator
map
,zipWithIndex
,map
和grouped
将不会创建中间集合(它们会创建新的迭代器)在我看来,这解释了为什么第一个例子更容易耗尽内存。