迭代器上的next()方法如何工作?

我对迭代器上的next()方法有疑问。 如果我作为我的代码的一部分这行(使用arrayOfStrings size = 4):

 Iterator it = arrayOfStrings.iterator(); //arrayOfString is ArrayList while(it.hasNext()) { String e = it.next(); System.out.println(e); } 

在第一次迭代中,迭代器开始指向索引为0的元素? 还是喜欢“索引-1”?

我问,因为据我所知next()方法返回集合中的下一个元素。

因此,如果在第一次迭代时,迭代器在调用next()时从索引0开始,它将返回索引1处的元素,并且我将无法对索引0处的元素执行任何操作?

next视为两步过程。 首先它获取迭代器中的下一个项目,然后它将指针递增以指向下一个项目。 因此,在创建新迭代器时,会初始化它以返回列表中的第一个项目(索引0)。

我想象迭代器工作方式的方法是将其视为索引之间的事物。 因此,当调用第next()时,您可以返回存储在[0]索引下的值,并且在该调用之后,迭代器在索引[0]和[1]之间等待下一次调用,以返回存储在索引处的值[1]。 在第二个next()之后,调用迭代器在[1]和[2]之间等待,依此类推……

这是我习惯迭代器的方法,但它可能对你有所帮助。

您显示的代码将正确打印ArrayList 所有元素it.next()调用在第一次调用时也是第一个元素 。 该元素通常用索引0表示。

请注意,您可能希望重命名arrayOfStrings因为从技术上讲它不是数组 ,它更像是List 。 用户可能因为名称而认为它是一个数组。


文档

在我看来,你是正确的,因为它是如此紧凑,方法的文档可能有点混乱:

返回迭代中的下一个元素。

然而,由于Iterator是一个非常常用的接口,因此描述可能需要如此详细,因为不仅仅是集合。 我可以想象一个类,其中第一个迭代元素不应该是底层结构的第一个元素。 例如,在给定点之前已经读取的某种流。 所以基本上由实现类来决定第一个元素是什么。 但对于集合,它将真正成为第一个元素 (索引0)。


对于-每个

另请注意,您显示的迭代等效于扩展的for循环 (for-each)在Java中的工作方式。 所以语法就像

 for (Item item : items) { ... } 

将被视为

 Iterator iter = items.iterator(); while(iter.hasNext()) { Item item = iter.next(); ... } 

实际上,这就是为什么你可以在扩展for循环中使用实现Iterable所有东西的原因。

知道这一点,如果iter.next()跳过第一个元素,那将更加令人困惑。 我的意思是名称for-each应该迭代所有元素。


洞察

让我们仔细看看该方法是如何实现的。 因此,我们将首先看到ArrayList#iterator作用。 看看它的源代码 :

 public Iterator iterator() { return new Itr(); } 

Itr类是ArrayList的私有类( 源代码 )。 这是Itr#next方法:

 @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } 

所以它本质上返回的是索引i处的元素,它是光标在调用方法时的位置。 它也已经将光标前进一个,以便下次调用该方法。

然而,由于以下原因,游标被隐式初始化为0

 int cursor; // Default value for int is 0 

所以next的第一次调用确实会返回索引0处的元素,这是第一个元素