几天前,我遇到了一个奇怪的错误,这个错误发生在我的地图缩减任务中。
最后,事实证明,实现ValueIterable
接口的hadoop Iterable
类创建了一个迭代器实例,并在每次调用iterator()
方法时返回它。
protected class ValueIterable implements Iterable<VALUEIN> {
private ValueIterator iterator = new ValueIterator();
@Override
public Iterator<VALUEIN> iterator() {
return iterator;
}
}
这意味着如果您迭代ValueIterable
一次,则无法再次迭代它。
我决定检查java documentation并且似乎每次都不需要Iterable
返回不同的迭代器(或者只是缺少要求?)。深入潜水我发现this回答说有一个迭代器违反Iterator
合同,因为它不能多次遍历集合。
谁在这里是对的? Iterable应该返回新的迭代器吗?为什么java文档不清楚?
这个hadoop类告诉客户端遍历是不可能的正确方法是什么?我的意思是如果它会抛出IllegalStateException
,是否会违反Iterator#hasNext()
方法合同?
答案 0 :(得分:2)
来自here:
从Iterable的iterator()方法中获得的迭代器是特殊的。这些值可能并非都在内存中; Hadoop可能正在从磁盘流式传输它们。它们并非真正由Collection支持,因此允许多次迭代是非常重要的。
没有实际定义的合同规定Iterator
返回的每个Iterable.iterator()
都应该重复相同的顺序。这只是一种习惯,因为它是预期的行为。
Hadoop - 或任何其他库 - 因此允许违反此规则。
java文档目前还不清楚这个目的 - 让Iterable
的实现者有任何摆动的空间来做任何他们想要的事情。
你应该怎么做 - 就像链接中提到的其他答案一样 - 保留已经迭代的项目列表以供以后重复迭代 - 但要注意,这可能是一个巨大的集合。活的hadoop环境,所以你可能会破裂。