Intro to Iterator in Java

  1. A iterator is a tool to iterate collections like ArrayList or HashSet. You could import it from java.util.
  2. The Iterator interface has four methods:
public interface Iterator<E> {
    E next();
    boolean hasNext();
    void remove();
    defalt void forEachRemaining(Consumer<? super E> action);
}
  1. The next() will return next elemet in a collection. But it will throw an NoSuchElementException if you reach the end of a collection.

  2. You could use hasNext. This method will return true if there are more elements to visit.

  3. next() and hasNext() can be used together to inspect each element in a collection.

    Collecton<String> c = ...;
    Iterator<String> iter = c.iterator();
    while (iter.hasNext()) {
        String element = iter.next();
    	...do something with element...
    }
    

    Java compiler will translate the for each loop into a loop with iterator

    for (String elements : element) {
        ...do something with element... 
    }
    

    The Collection interface extends the Iterator interface, so you can use for each loop with any collections in the std.

  4. You can call the forEachRemaining with Lambda expression as a susbstitution with loop.

    iterator.forEachRemaining(elem -> ...do something with element...);
    

    If you traverse an ArrayList, iterator will start from index 0, however, if you traverse through a HashSet, it will be iterate in a random order.

  5. Difference between iterators in the Java Collections library and iterators in other libraries(C++ etc.).

    Iterator in others library can be look up via index.

    The only way for Java iterator to look up is to call next. You can think the Java iterator as being between elements.

    image-20221019165839127
  6. The remove mthod of the iterator interface removes the element that was return by the last call to next. (You need to see the element before you decide this is the one you want to remove.)

    Iterator<String> it = c.iterator();
    it.next(); // skip over the first element
    it.remove();
    

    There is a dependency betweem the calls to next and remove.

    You can not do this:

    ic.remove();
    ic.remove(); // throw an IllegalStatementException
    

    You need do this:

    ic.remove();
    ic.next();
    ic.remove();
    
  7. Why use iterator or the difference between for (for each) and iterator?

    My general rule of thumb is: use the foreach loop, unless you really need capabilities of an Iterator. I would only use for loop with indices with arrays, when I need access to the index inside the loop. -- Iterator vs for

Strength or use case: remove while iterating.

Weakness: readbility and *efficiency

So use for each first if your want to iterate something. Use indexed for loop if you need indeces or loop an array. If you need to remove when iterating, you could use iterator.

An object should be in control of its own state. And one situation is that, if the add method has something else before the add in your self defined collection. And you could use iterator to only manipulate the collection.

class MyClass
{
    private ArrayList<Item> myList;

    public MyClass()
    {
        myList = new ArrayList();
    }

    public addItem( Item item )
    {
         item.doSomething(); // Lets say that this is very important before adding the item to the array.
         myList.add( item );
    }
}
public ArrayList getList()
{
    return myList;
}

Somebody could get the reference to myList through this method and add items to the array, without calling item.doSomething();