hitesh
hitesh

Reputation: 378

Understanding iterator.next functioning

Iterator<String> ir = arr.iterator();

while(ir.hasNext()) { 
    String an = ir.next();
    System.out.println(an);
}

In ArrayList ir returns a list object pointing to first. Now ir.next() must point to next object. So why it is pointing to the first object when run first time in loop?

Additionally,

ListIterator<String> ir= arr.listIterator();

while(ir.hasNext())
{ 
    String an= ir.next();

    ir.set(an + '+');

    System.out.println(an);
}

Why its not appending the '+' ?. It just prints the original ArrayList.

Upvotes: 0

Views: 683

Answers (2)

rgettman
rgettman

Reputation: 178253

It's not a problem that the Iterator is pointing to the first item before it's called for the first time.

What happens in next is the following:

  1. Store the current value to be returned later.
  2. Advance index to the next value beyond the current value (or "nothing" if off the end of the list).
  3. Return the current value from step 1.

It really is pointing to the "next" value at all times, even if the iteration is done and there are no more items, in which case there is no "next" item.

Here's example source code from ArrayList's iterator, an inner class called Itr:

private class Itr implements Iterator<E>
    int cursor;       // index of next element to return

The default value is 0, which already points to the first element.

The next() method performs the steps above (plus some other steps to prevent modification during iteration).

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

Upvotes: 0

Vivin Paliath
Vivin Paliath

Reputation: 95508

hasNext() merely tells you if there is another element in the collection that you can iterate over. next() actually returns said element. The initial position of the cursor is before the first element.

For example, assume you had the following:

  0   1   2   3   4
| 8 | 5 | 2 | 3 | 7 |

The cursor is actually pointing to a location before the first element:

    0   1   2   3   4
  | 8 | 5 | 2 | 3 | 7 |

^
|
cursor

When you do hasNext(), it checks to see if there is anything at location cursor + 1. If you have an empty list, there is nothing at cursor + 1 (i.e., nothing at index 0), so it will return false. If you are at the very last element, cursor + 1 == list.size() which means there is nothing after the end of the list. If you are anywhere else in the list, cursor + 1 is a valid index that is populated, so it will return true.

When you actually do next(), it will advance the cursor and return the element at the new position. Now, the cursor is in a new location where it is before the next element.

Now it really doesn't even matter how it is being done internally. The cursor could be pointing to the very first element the first time. If that is the case, all you would need is special logic to handle that scenario (perhaps a flag that checks to see if next() has ever been called).

All you need to understand in the case of an Iterator is that hasNext() will tell you if there is an element remaining that you can iterate over, and next() will return that element. This behavior is consistent across invocations and should be consistent across all implementations.

Upvotes: 6

Related Questions