How does next() method on iterators work?

2020-02-14 10:20发布

I have a doubt with the next() method on iterators. If I have as a part of my code this lines (with arrayOfStrings size = 4):

Iterator<String> it = arrayOfStrings.iterator(); //arrayOfString is ArrayList<String>

while(it.hasNext()) {
    String e = it.next();
    System.out.println(e);
}

At the very first iteration, the iterator starts pointing to element with index 0? or like the "index -1" ?

I ask because as far as I know the next() method returns the next element in the collection.

So, if at the very first iteration the iterator starts at index 0 when next() is invoked, it returns the element at index 1 and I won´t be able to do nothing with the element at index 0?

标签: java iterator
3条回答
甜甜的少女心
2楼-- · 2020-02-14 11:05

The code you show will correctly print all elements of the ArrayList. The it.next() call will, at its first call, also the first element. This element is usually denoted with index 0.

Note that you might want to rename arrayOfStrings as technically it's no array, it's more a List. A user might due the name think that it is an array.


Documentation

In my opinion you are right that the documentation of the method can be a bit confusing since it is so compact:

Returns the next element in the iteration.

However the description probably needs to be so undetailed since Iterator is a very frequently used interface, not only for collections. I could imagine a class where the first iteration element should not be the first element of the underlying structure. For example some kind of stream that was already read until a given point. So basically it is up to the implementing class to decide what the first element is. But for collections it will truly be the first element (index 0).


For-each

Also note that the iteration you show is equivalent to how the extended for-loop (for-each) works in Java. So a syntax like

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

will be treated like

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

In fact this is the reason why you can use everything that implements Iterable in extended for loops.

Knowing this it would rather be confusing if iter.next() would skip the first element. I mean by the name for-each is supposed to iterate all elements.


Insights

Let's take a closer look at how the method is implemented. Therefore we will first see what ArrayList#iterator does. Take a look at its source code:

public Iterator<E> iterator() {
    return new Itr();
}

The Itr class is a private class of ArrayList (source code). And here is the Itr#next method:

@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];
}

So what it essentially returns is the element at index i which is where the cursor was at the point of calling the method. It also already advances the cursor by one for the next call of the method.

The cursor however is implicitly initialized with 0 due to:

int cursor; // Default value for int is 0

So the first call of next will indeed return the element at index 0 which is the first element.

查看更多
够拽才男人
3楼-- · 2020-02-14 11:09

My way to imagine the way iterators work is to think about it as the thing that is placed between the indexes. So when the first next() is being called you can return the value stored under the [0] index and after that call, iterator waits between index [0] and [1] for the next call to return for you value stored at index [1]. After the second next() call iterator waits between [1] and [2] and so on...

It is just my way to get used to iterators but it might be helpful for you some way.

查看更多
【Aperson】
4楼-- · 2020-02-14 11:14

Think of next as a two-step process. First it gets the next item in the iterator, then it increments the pointer to point to the next item. So, when you create a new iterator, it is initialized to return the first item (index 0) in your list.

查看更多
登录 后发表回答