Java iterator hasNext() method allways false - java

We have a HashSet of objects:
private Set<Client> clients = new HashSet<Client>();
And iterator for it:
private Iterator<Client> iterator = clients.iterator();
Lets add object to that set and print out iterators hasNext method output:
Client client = new Client(name);
clients.add(client);
System.out.println(iterator.hasNext());
The output is: "false". Why?

The Iterator for the HashSet class is a fail-fast iterator. From the documentation of the HashSet class:
The iterators returned by this class's iterator method are fail-fast:
if the set is modified at any time after the iterator is created, in
any way except through the iterator's own remove method, the Iterator
throws a ConcurrentModificationException. Thus, in the face of
concurrent modification, the iterator fails quickly and cleanly,
rather than risking arbitrary, non-deterministic behavior at an
undetermined time in the future.
Here is a nice detailed explanation of the Iterator internal implementation.

The iterator never changes once created--it only works on the elements that were in the set when you got it. It doesn't recognize that after you've created it, you added an element. Just re-get the iterator after all elements have been added.

See this:
http://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html
Iterators break if you modify the collection externally after getting the iterator

Related

What is the purpose of synchronizing the traversal block if we are using Collections.synchrnizedList(Collection c)?

What is the purpose of synchronizing the traversal block if we are using Collections.synchrnizedList(Collection c)?
I am using Collections.synchronizedList() method to get a synchronised version of arrayList,then why am I supposed to put the traversal of arraylist in a synchronised block?
So, I am going through a tutorial on how to make arraylist synchronous. I came across following line of code.
import java.util.*;
class GFG
{
public static void main (String[] args)
{
List<String> list =
Collections.synchronizedList(new ArrayList<String>());
list.add("practice");
list.add("code");
list.add("quiz");
synchronized(list)
{
// must be in synchronized block
Iterator it = list.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
}
My question is why are we synchronizing the traversal?
Even if there were to be two threads traversing simultaneously and if both try to structurally modify array simultaneously it should not be possible bcz if one thread is adding element won't it have lock over the synchronised arraylist?
The iterator returned by ArrayList will fail with a ConcurrentModificationException if the list is modified after the iterator is created. For that reason, the code is preventing modifications to the list while iterating. Per the ArrayList docs:
The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the list is structurally modified at any
time after the iterator is created, in any way except through the
iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException. Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than
risking arbitrary, non-deterministic behavior at an undetermined time
in the future.
Not all List implementations have this particular behavior. For instance, with CopyOnWriteArrayList iteration does not fail when there are concurrent modifications.

Foreach against for(int...) loop - why does foreach raises exceptions when removing elements? [duplicate]

This question already has answers here:
Calling remove in foreach loop in Java [duplicate]
(11 answers)
Closed 9 years ago.
I was wondering why I cannot remove elements from a list, when I'm iterating it with a foreach-loop like:
List<Object> objects = new ArrayList<Object>();
Object one = new Object();
Object two = new Object();
Object three = new Object();
objects.add(one);
objects.add(two);
objects.add(three);
and then removing the elements like:
foreach(Object o : objects){
objects.remove(three); //I know that o is my current object
}
It seems like the foreach-loop doesn't allow to remove objects, which are "still" in the loop-queue. Am I correct?
And why does the for-int-loop doesn't care about this? In this loop I can easily remove objects, which are still in the loop.
Thanks
Well, initially the question was tagged C#, now removed. however....
It's not true that a for/loop doesn't care if you remove an element from the collection.
If you remove elements while going forward, you will have problem indexing elements after the one you have removed because the index doesn't match anymore your next element.
You avoid problems with for/loop only if you loop in reverse order (from the last element to the first)
The foreach suffers internally of the same problem. The enumerator maintains a Current position to the element, if you remove the element and then advance to the Next position, the Current indexer doesn't point to the element after the one removed, but to an element two position after the one removed.
For example:
Suppose a string collection of "birds", "animals", and "fishes"
At the foreach start, the internal Current is 0 ( points to "birds")
you remove "birds", so "animals" is at index 0 (where Current still points to)
You advance to the Next element (Current=1, points to "fishes")
Without the exception the Next advance will exit the loop.
foreach has not been designed to allow this scenario.
As far as Java is concerned, the answer is in the javadoc (emphasis mine):
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
For Java at least, you are correct: the problem is the iterator used to go through the elements in the list does not allow modification. It will throw a ConcurrentModificationException. To quote the Java API javadoc for java.util.ArrayList
The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the list is structurally modified at any
time after the iterator is created, in any way except through the
iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException. Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than
risking arbitrary, non-deterministic behavior at an undetermined time
in the future.
The alternative is to use an iterator that allows such modifications, rather than the default for ArrayList or to create the iterator explicitly, rather than use the foreach loop, and use the methods it has to alter the contents whilst iterating through the list.
See Calling remove in foreach loop in Java, in general use Iterator and check with hasNext if there are more elements

fail-fast iterator

I get this definition : As name suggest fail-fast Iterators fail as soon as they realized that structure of Collection has been changed since iteration has begun.
what it mean by since iteration has begun? is that mean after Iterator it=set.iterator() this line of code?
public static void customize(BufferedReader br) throws IOException{
Set<String> set=new HashSet<String>(); // Actual type parameter added
**Iterator it=set.iterator();**
First of all, they are fail-fast, not fail-safe.
The contract is that structural modifications (i.e. insertions/deletions) of certain types of collections invalidate existing iterators into the collection. Fail-fast iterators attempt to detect that they are not supposed to be valid and throw a ConcurrentModificationException. This is done as a service to you, the programmer, to help discover this type of bugs quicker.
In your example:
Iterator it = set.iterator();
it.next();
set.add("unique-entry"); // invalidates the iterator
it.next();
If you're lucky, the second it.next() will detect the invalid usage and throw an exception. Note that this is done on a best-effort basis and is not guaranteed.
is that mean after Iterator it=set.iterator() this line of code?
Yes. If you look at the code for HashSet.iterator() you'll see it's just this:
return map.keySet().iterator();
... which delegate's to HashMap.KeySet.iterator(). There are a few more links in the chain, but eventually you get to HashMap.HashIterator, which contains this in the constructor:
private abstract class HashIterator<E> implements Iterator<E> {
int expectedModCount; // For fast-fail
...
HashIterator() {
expectedModCount = modCount;
...
}
}
... where modCount is a field in the enclosing instance of HashMap which keeps track of the number of modifications.
The iterator being fail-fast means the following piece of code is expected to fail:
Set<String> set = new HashSet<String>();
Iterator<String> it = set.iterator();
set.add("");
it.next(); // the set has changed now, and the iterator will throw an exception
because the following series of events occur: The iterator is created, then its underlying collection changes, then the iterator is accessed.
yes, don't change the collection after using .iterator() if you are planning to iterate over it , you can use the .remove() if you want to remove the latest element though
Before Fail Fast Iterator is starting to work it’s getting count of collection and after any iteration it is checking if count is changed or not, and in case of changed count JVM will throw ConcurrentModificationException. Fail fast iterators are any iterator of collection which is inside java.util package(e.g. ArrayList, LinkedList etc) and Fail Safe iterators are iterators which are inside of java.concurrent package(e.g. CopyOnWriteArrayList, CopyOnWriteSet etc.). Fail Fast iterators will throw exception in case of concurrent modification but Fail Safe iterator is basically working with copy of collection which is not throwing exception in case of concurrent modification.

ConcurrentModificationException thrown on iterator.remove

I'm getting a ConcurrentModificationException despite using the iterator to perform the remove operation. Any ideas as to why?
for (Iterator<Thread> iter = threads.iterator(); iter.hasNext();) {
Thread hook = iter.next();
if(someCondition){
iter.remove();
}
}
From JavaDoc Iterator.remove():
Removes from the underlying collection the last element returned by
the iterator (optional operation). This method can be called only once
per call to next. The behavior of an iterator is unspecified if the
underlying collection is modified while the iteration is in progress
in any way other than by calling this method.
It seem that the behavior is depended to the collection. Also as aioobe pointed out. I can reproduce ConcurrentModificationException when I modify the collection somewhere else. Using only Iterator interface, I can only reproduce IllegalStateException.
Because you have a modification concurrent to using an Iterator, which is not supported. Either iterate a list clone, or use a CopyOnWriteArrayList.
Or memory what to remove in a new list, and call list.removeAll(whatIWantedToRemove) afterwards.

Concurrent Modification Exception thrown by .next from Iterator

Not sure exactly what's wrong here:
while(itr.hasNext())
{
Stock temp =itr.next();
}
This code is throwing a ConcurrentModificationException at itr.next();
Initialization for the iterator is
private Iterator<Stock> itr=stockList.iterator();
Any ideas?
[The basic code was copied directly from professor's slides]
This could be happening because of two reasons.
Another thread is updating stockList either directly or through its iterator
In the same thread, maybe inside this loop itself, the stockList is modified (see below for an example)
The below codes could cause ConcurrentModificationException
Iterator<Stock> itr = stockList.iterator();
while(itr.hasNext())
{
Stock temp = itr.next();
stockList.add(new Stock()); // Causes ConcurrentModificationException
stockList.remove(0) //Causes ConcurrentModificationException
}
Some other thread is modifying the underlying collection? I suspect that there is code above what you are showing us that causes the problem: a mod to the collection between the call to iterator() and the loop.
Most plausible reason is that some code has modified the underlying collection after you obtained your iterator.
Form javadoc:
The iterators returned by this class's
iterator and listIterator methods are
fail-fast: if the list is structurally
modified at any time after the
iterator is created, in any way except
through the iterator's own remove or
add methods, the iterator will throw a
ConcurrentModificationException. Thus,
in the face of concurrent
modification, the iterator fails
quickly and cleanly, rather than
risking arbitrary, non-deterministic
behavior at an undetermined time in
the future.

Categories