In the first version of the code a new instance of the Iterator is created during each iteration of the loop, because the ArrayList#iterator() method is invoked. Calling iterator() will return a new Iterator instance each time. I suspect you may be thinking iterator() works similar to a Java beans getXXXX accessor, however it does not.
//new Iterator Instance will always have a next item
//Iterator is a different instance during each iteration
while(myList.iterator().hasNext()) {
System.out.println(myList.iterator().next());
}
System.out.println();
The second version of the code assigns the Iterator to a variable, which causes the hasNext() method to be invoked on the same Iterator instance. Since this iterator instance has its .next() method invoked for each loop iteration it performs as you would expect and eventually ends the loop when hasNext returns false.
//Same instance of the iterator for each iteration
Iterator itr = myList.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
In a nutshell
Iterator itr = myList.iterator();
Iterator itr2 = myList.iterator();
System.out.println(itr == itr2 ? "Same":"Different"); //outputs Different
It may also help you to see the source code for ArrayList#iterator:
//notice how a new instance of the Nested Itr class is created
public Iterator<E> iterator() {
return new Itr();
}