My problem is simple : listeBalles is an ArrayList<Balle> and here is my code :
for (Balle b : listeBalles) {
b.changeList(listeBalles);
}
The matter is that the method b.changeList adds a Balle to the ArrayList listeBalles. I think that this is the matter. Here are the exceptions :
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at Main.main(Main.java:31)
The line pointed is the for (Balle b : listeBalles) { line.
Thank you for your help.
Yes, you're right. From ArrayList's 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.
So basically you're not allowed to modify the List during iterating over it. What is your actual question?
As you cannot add elements to an ArrayList you're currently iterating over, make a copy of that list first.
E.g. try:
for (Balle b : new ArrayList(listeBalles)) {
b.changeList(listeBalles);
}
The cause is that you are iterating through the List and modifying it at the same time.
You cannot modify the content of a collection or array while you iterate over it in a for-each loop. What are you actually trying to do?
Related
I am getting ConcurrentModificationException when executing the following code:
public void refreshAvailableCaseSettings() throws Exception {
//getAvailableCases() returns reference to the instance variable
LinkedHashMap<Integer, CaseSetting> cases = getAvailableCases();
/* java.util.ConcurrentModificationException even after trying entryset()
for(Map.Entry<Integer, CaseSetting> entry : cases.entrySet()){
entry.getValue().refresh(false);
}
*/
// java.util.ConcurrentModificationException
Iterator casesIterator = cases.values().iterator();
while (casesIterator.hasNext()) {
CaseSetting caseSetting = casesIterator.next();
//refresh() updates caseSetting state by getting setting info from DB
caseSetting.refresh(false);
}
}
Error:
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:719)
at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:752)
at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:750)
I am not modifying the map by adding or removing elements. Please help me to understand the issue here.
The general contract for using iterators is this:
While an iterator over a collection is in progress, the underlying collection must not be modified.
You can do whatever you want on the elements of the collection, but you must not touch the collection itself.
You are getting a ConcurrentModificationException because a part of your code within the while loop does exactly that - it changes the underlying collection.
A standard approach is to either (a) create a new copy of the collection and iterate over this read-only copy, or (b) put the changes into a separate collection.
What refresh function does ? According to my understanding you are getting these only because you are modifided HashMap while iterating it,
I used to get these error when I used to put something in map, means size was increasing.
Also you need to put everything in question, like CaseSetting class
This question already has answers here:
Getting a ConcurrentModificationException thrown when removing an element from a java.util.List during list iteration? [duplicate]
(11 answers)
Closed 9 years ago.
my classes:
class Game{
ArrayList<Block> blocks;
public ArrayList<Block> getBlocks(){return blocks;};
}
class Block{
if(conditon) {
game.getBlocks().remove(this);
}
}
I have these classes, the ArrayList contains over 10 Block instances, if the condition for remove the current block in the Block class is true, i need remove this block from the ArrayList, but i got the Exception..
While iterating the Arraylist, you are not allowed to remove any item. If you want to remove an item while iteration, you can add removed item into newly created ArrayList say,.
willBeRemovedList after iteration completed you can remove all of them at a time.
ConcurrentModificationException is thrown by iterator because you modified a list and he can't get nextElement because he doesn't know what really happened to list he is iterating over.
for (Block block : blocks) {
blocks.remove(block);
}
This will throw exception when for loop tries to get next element of modified list, since Iterator is instantiated in the beginning of looping through list, iterator will be unable to choose right next element and will throw exception.
You can however remove current element from list you are iterating, but it should be done though Iterator itself. You would do something like this:
for (Iterator<Block> iterator = blocks.iterator(); iterator.hasNext(); iterator.next()){
iterator.remove();
}
The documentation of ArrayList class cleanly tells us the reason and how to avoid it:
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.
If a fail-fast iterator detects
that a modification has been made during iteration, it throws
ConcurrentModificationException, which is an unchecked exception. It is highly probable that you are iterating and modifying your collection in the same loop.
Also, the collections classes in the java.util package all return fail-fast iterators,
which means that they assume a collection will not change its contents during
the time a thread is iterating through its contents.
I would like to iterate over a Set and remove the elements from the set that match some condition. The documentation of iterator says nothing about modifying the list while iterating over it.
Is this possible? If not, what would be the best way to do it? Note that I only want to remove elements from the set that are provided by the Iterator.
Edit: Quickly was shown that this is possible. Can I also do it with the following syntax?
for(Node n : mySet) {
mySet.remove(n);
}
Yes, you can use the iterator to remove the current element safely:
iterator.remove();
The javadoc of remove() says:
Removes the specified element from this set if it is present (optional operation). More formally, removes an element e such that (o==null ? e==null : o.equals(e)), if this set contains such an element. Returns true if this set contained the element (or equivalently, if this set changed as a result of the call). (This set will not contain the element once the call returns.)
Answer to your next question: No, you can't. Modifying a set while iterating over it with an enhanced for loop will cause a ConcurrentModificationException.
The answer of tangens is correct. If you don't use iterator.remove() but remove directly from Set, you will receive an exception call ConcurrentModificationException
This has actually improved in Java 8. Now you can just
mySet.removeIf(element -> someConditionMatches());
The above is implemented as a default method in java.util.Collection and should save everyone from writing boring loops. That said, it should work for any type of collection, and not just Set.
This ist what .remove() does:
http://download.oracle.com/javase/6/docs/api/java/util/Iterator.html#remove%28%29
"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. "
for(Node n : mySet) {
mySet.remove(n); }
wont work since you are modifying the set you are iterating. This however can only be done using the iterator which is not the case this way.
This is one disadvantage of using enhanced for loops.
I'm using a enhanced for loop over an ArrayList and wanted to remove some elements that contain a particular value.
When I try to do this I get the above exception. I've had a look around and it seems using a enhanced for loop while modifying the collection is a bad idea. How else would I go about this?
thanks for any help.
You can keep a list of the items to be removed, then call removeAll after the loop has finished.
Vector toRemove=new Vector();
for (Object o: array){
if(remove(o)) toRemove.add(o);
}
array.removeAll(o);
You should get an Iterator for the collection, walk that and call the remove() method on the iterator when you want to remove an element. Please be advised that not all Iterator implementations support remove(), it's an optional method!
for(Iterator it = collection.iterator(); it.hasNext();) {
Object element = it.next();
if(.. should remove element ..)
it.remove()
}
You cannot use the enhanced for loop to do this as you do not have access to the Iterator being used. You need to use a regular for loop and remove elements of the ArrayList via Iterator.remove().
Take this Java code:
for (ContactsReduced curContact : allcontacts) {
..........
allcontacts.remove(curContact);
}
I do based on a condition a remove, will the foreach miss the next item in order, and do we need to step back(somehow)?
That code will break with most collections - other than a few collections such as those in java.util.concurrent, modifying a collection while iterating over it isn't supported.
A few options:
Obtain and use an iterator explicitly (call iterator() on the collection) instead of an enhanced for loop, and call iterator.remove() to remove an item
Use a plain for loop, either moving forwards and stepping back after the removal or moving backwards from the end
Maintain a separate list of items to remove, and then remove them after iterating
Take a look at the section on iterators on the collection interface tutorial
Use Iterator instead of the for-each construct when you need to remove the current element. The for-each construct hides the iterator, so you cannot call remove. Therefore, the for-each construct is not usable for filtering.
Note that Iterator.remove is the only safe way to modify a collection during iteration
List<Integer> al = new ArrayList<Integer>();
for(int i=0;i<10;i++){
al.add(i);
}
for(Integer x:al){
al.remove(x);
System.out.println(al);
}
Well, the question is interesting so I tried it in my system and this is wat i got.
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at test.Main.main(Main.java:17)
It's definitely advised against to tamper with the collection while iterating it. I'm not sure if Java even allows it; it might throw an exception. I know C# does...
Iterator will fail with ConcurrentModificationException. That's how collection framework is designed.