我对迭代器上的next()
方法有疑问。如果我将此行作为我的代码的一部分(arrayOfStrings
size = 4):
Iterator<String> it = arrayOfStrings.iterator(); //arrayOfString is ArrayList<String>
while(it.hasNext()) {
String e = it.next();
System.out.println(e);
}
在第一次迭代中,迭代器开始指向索引为0的元素?或者像“index -1”?
我问,因为据我所知,next()
方法返回集合中的下一个元素。
因此,如果在第一次迭代时,迭代器在调用next()
时从索引0开始,它将返回索引1处的元素,并且我将无法对索引0处的元素执行任何操作?
答案 0 :(得分:2)
将next
视为两个步骤。首先它获取迭代器中的下一个项目,然后它将指针递增以指向下一个项目。因此,当您创建一个新的迭代器时,它会被初始化以返回列表中的第一个项目(索引0)。
答案 1 :(得分:0)
您展示的代码将正确打印ArrayList
的所有元素。 it.next()
电话会在第一次通话时也是第一个元素。此元素通常用索引0 表示。
请注意,您可能希望重命名arrayOfStrings
,因为技术上它不是数组,它更像是List
。用户可能因为名称而认为它是一个数组。
在我看来,你是对的documentation of the method可能有点令人困惑,因为它太紧凑了:
返回迭代中的下一个元素。
然而,描述可能需要如此详细,因为Iterator
是一个非常常用的界面,不仅适用于集合。我可以设想一个类,其中第一个迭代元素不应该是底层结构的第一个元素。例如,在给定点之前已经读取的某种流。所以基本上由实现类来决定第一个元素是什么。但对于集合来说,它确实是第一个元素(索引0)。
另请注意,您显示的迭代等同于扩展for循环(for-each)在Java中的工作方式。所以像
这样的语法for (Item item : items) {
...
}
将被视为
Iterator<Item> iter = items.iterator();
while(iter.hasNext()) {
Item item = iter.next();
...
}
实际上,这就是为什么你可以在扩展for循环中使用实现Iterable
的所有内容的原因。
如果iter.next()
跳过第一个元素,那么它会更加令人困惑。我的意思是名称 for-each 应该迭代所有元素。
让我们仔细看看该方法是如何实现的。因此,我们将首先看到ArrayList#iterator
的作用。看看它的source code:
public Iterator<E> iterator() {
return new Itr();
}
Itr
类是ArrayList
(source code)的私有类。 here是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
处的元素,即第一个元素。
答案 2 :(得分:0)
我想象迭代器工作方式的方法是将其视为放在索引之间的东西。因此,当调用第一个next()
时,您可以返回存储在[0]索引下的值,并且在该调用之后,迭代器在索引[0]和[1]之间等待下一次调用,以便为您返回值在索引[1]。在第二个next()
调用之后迭代器在[1]和[2]之间等待,等等......
这只是我习惯迭代器的方法,但它可能对你有所帮助。