为什么Iterable没有义务在每次调用迭代器()方法时返回新的迭代器



几天前,我遇到了一个奇怪的错误,这个错误发生在我的地图缩减任务中。

最后,实现Iterable接口的hadoop ValueIterable类创建了一个迭代器实例,并在每次调用iterator()方法时返回它。

protected class ValueIterable implements Iterable<VALUEIN> {
  private ValueIterator iterator = new ValueIterator();
  @Override
  public Iterator<VALUEIN> iterator() {
    return iterator;
  } 
}

这意味着,如果您在ValueIterable上迭代一次,就无法再次迭代。

我决定查看java文档,它似乎不需要Iterable每次都返回不同的迭代器(或者只是缺少要求?)。更深入地研究,我发现这个答案告诉我们,使用单个迭代器违反了Iterator约定,因为它不能多次遍历集合。

  1. 这里谁是正确的?Iterable应该返回新的迭代器吗?为什么java文档不清楚?

  2. 这个hadoop类告诉客户端遍历是不可能的,正确的方法是什么?我的意思是,如果它会抛出IllegalStateException,它会违反Iterator#hasNext()方法合同吗?

从这里开始:

从Iterable的迭代器()方法接收到的迭代者是特殊的。这些值可能并不都在内存中;Hadoop可能正在从磁盘进行流式传输。它们并没有真正得到Collection的支持,因此允许多次迭代是不重要的。

没有实际定义的约定规定Iterable.iterator()返回的每个Iterator应该重复相同的序列。这只是一种习惯,因为这是意料之中的行为。

Hadoop或任何其他库因此被允许打破这方面的规则。

java文档不清楚这到底是为了什么目的——让Iterable的实现者有回旋余地,可以用他们想要的任何方式来做。

你应该如何做——就像链接中提到的其他答案一样——保留一个已经迭代的项目列表,以便以后重复迭代——但请注意,这可能是实时hadoop环境中的一个巨大集合,所以你很可能会崩溃。

最新更新