【发布时间】:2015-09-25 09:54:39
【问题描述】:
我有一个函数定义如下(为了论证而简化):
def sendRecords(records: Iterator[Map[String, String]]) = {
records.sliding(10,10).foreach { case recordList => println(recordList) }
}
当我调用这个函数时,我可以从 println(并且知道预期的答案是什么)看到 recordList 确实是一批 10,但不知何故,“记录”中的某些项目似乎被跳过了。在这种情况下,输出缺少第 1 个、第 12 个、第 13 个、第 24 个、第 25 个……(即似乎有一些奇怪的规律性)。请注意,每个单个元素都是 string-> string 的映射(并且内容是机密的),但为了说明起见,输出的简化形式可以是
[1,2,3,4,5,6,7,8,9,10],[13,14,15,16,17,18,19,20,21,22],[....]
对于批处理案例和
[0,1,2,3,4,5,6,7,8,9], [10,11,12,13,14,15,16,17,18,19],[....]
对于“toList.iterator”(见下文)的情况,这是可以预料的。在这些输出中,我已将地图替换为标识它们的索引。
我完全不知道为什么会发生这种情况。请注意,“记录”是我自己实现的迭代器(即使用 hasNext 和 next)——我怀疑这很重要。但是,实现相当复杂。我在底部添加了主要部分。
不过,有一些迹象表明它是正确的
records.toList.iterator.sliding(10,10).foreach { case recordList => println(recordList) }
工作正常,那
records.foreach { println }
看起来也符合预期(即它单独打印每个元素,并且列表是完整的)。
有人知道这里有什么吗 - 或者建议我可以尝试一些其他的事情吗?任何帮助将非常感激。我正在使用 scala 2.10.5。
(请注意,虽然 toList.iterator hack 有效,但在这里它是不可接受的,因为这会在内存中构建整个列表,这在生产中会太大)。
谢谢! -乔里斯。
迭代器还没有完全整理好,所以请原谅一些潜在的狡猾代码(这可能导致了这个问题),但它的想法是遍历一个逗号分隔的文件(即“行”输入)有一个相当复杂的标题定义(因此是状态方法)。我不能展示解码器,因为那是保密的,但我希望这应该足够了。也许我的 hasNext/next 有缺陷。
class DecodingIterator(lines: Iterator[String]) extends Iterator[Map[String, String]] {
val decoder = new StatefulDecoder()
var cachedRecord = Map[String,String]()
def hasNext: Boolean = {
if (!lines.hasNext || decoder.inState(decoder.Finished()))
false
else {
while(!decoder.inState(decoder.Data())) {
decoder.processLine(lines.next)
}
decoder.processLine(lines.next)
cachedRecord = decoder.lastRecord
!decoder.inState(decoder.Finished())
}
}
def next = cachedRecord
}
【问题讨论】:
-
你能提供你的迭代器实现、预期输出和实际输出吗?
-
您确实应该添加
records迭代器的代码。不相关,可以将sliding(10, 10)替换为grouped(10)。 -
是的,我已经添加了迭代器的主要部分。它依赖于我无法展示的“StatefulDecoder”。但现在应该有希望充分说明 hasNext/next 逻辑。
-
我想知道“it.hasNext”是否在“it.next()”之前被多次调用。从我的实现中可以看出,重复调用 it.hasNext() 并不是幂等的。
-
@JorisPeeters 这确实是正在发生的事情,在每个切片
hasNext被调用两次之前,所以你会丢失 1 个元素。
标签: scala