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.
Related
According to the javadocs,conncurrent modification exception will be thrown when we will try to structurally modify the collection while iterating over it.Only iterator remove method will not throw concurrent modification exception.
I have analyzed following cases where concurrent modification exception will not be thrown:
List<Integer> var=new ArrayList<Integer>();
var.add(3);
var.add(2);
var.add(5);
1st case:
for(int i = 0; i<var.size(); i++){
System.out.println(var.get(i));
var.remove(i);
}
2nd Case:
for(Integer i:var){
System.out.println(i);
if(i==2){
var.remove("5");
}
}
1)Can anyone please explain how these cases are not throwing Conncurrent Modification Exception?
2)Can anyone please tell how iterator.remove internally works?
The first implementation isn't using an iterator, so of course it doesn't throw. It's only Iterators that throw (though even the indexed for-loop will be corrupted, e.g. if you remove an element and then the indexes of all the other elements shift out from under your iteration). Java just won't be able to tell you.
The second implementation isn't changing the contents. var.remove("5") attempts to remove the string "5", which isn't present (the list only contains integers), so no change happens. Additionally, i == 2 is dangerous when i is a boxed capital-I Integer; consider doing for (int i : var) instead.
Finally, no implementation guarantees that a ConcurrentModificationException will be thrown; it only tries to do so to warn you your iterator has been corrupted. Whether or not an exception is thrown, the iterator is corrupted by modifications performed while an iteration is in progress, Java's just trying to warn you.
According to the Javadoc of 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.
So, the conditions under which a CME will be thrown are:
There must be an iterator (or a list iterator)
You must perform a structural modification of the list not via the iterator (i.e. add or remove an element)
And, perhaps not quite so obviously:
After the structural modification, you must call a method on an iterator created before the structural modification.
i.e. the iterator doesn't attempt to detect the CME until you call next() or remove() on it.
The Deque class' Javadoc says:
The iterators returned by this class's iterator method are fail-fast:
If the deque is modified at any time after the iterator is created, in
any way except through the iterator's own remove method, the iterator
will generally 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.
However, the below program behaves differently:
[EDIT]: I am getting error while pasting the whole code "An error occurred submitting the edit". Whew! C'mon SO.
// create an empty array deque with an initial capacity
Deque deque = new ArrayDeque(8);
// use add() method to add elements in the deque
deque.add(15);
deque.add(22);
deque.add(25);
deque.add(20);
System.out.println("printing elements using iterator:");
for(Iterator itr = deque.iterator();itr.hasNext();) {
System.out.println(itr.next());
deque.remove(); //deque is modifed after the iterator is created
}
I expected it to throw ConcurrentModificationException, but it simply prints the following output:
printing elements using iterator:
15
22
25
20
Any idea why?
It looks like it's because you consume the first element of the iterator before removing it. If you change your code to
for(Iterator itr = deque.iterator();itr.hasNext();) {
deque.remove();
System.out.println(itr.next());
}
then you'll see the exception. Your original implementation does indeed contradict the documentation.
However, looking in the implementation of ArrayDeque's iterator implementation, the next() method has this code:
E result = (E) elements[cursor];
// This check doesn't catch all possible comodifications,
// but does catch the ones that corrupt traversal
if (tail != fence || result == null)
throw new ConcurrentModificationException();
Note the following paragraph in the Deque's Javadoc:
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
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
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.
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.