迭代器上的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
处的元素,这是第一个元素 。