Think about what this line is doing:
while (p.iterator().hasNext()) {
Each time you want to evaluate the condition, you're getting a new iterator object, that has never been touched before.
Since you've never consumed anything from the new iterator, hasNext()
will always be true.
Likewise, on the next line:
System.out.println(p.iterator().next().getCity());
You are getting another new iterator, so calling next()
on it will always return the first item in the list.
In order to loop correctly, you need to reuse the same iterator for the entirety of the loop. You can do this either by explicitly creating and using a single iterator like so:
Iterator<Person> itr = p.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().getCity());
}
or you can use something like an enhanced for-loop and let Java implicitly create and manage the iterator:
while (Person person : p) {
System.out.println(person.getCity());
}
which is functionally equivalent to
for (Iterator<Person> itr = p.iterator(); itr.hasNext();) {
Person person = itr.next();
System.out.println(person.getCity());
}