I'm trying to iterate throuh a list while already looping through it (nested loops). Consider the code below:
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
for(int i : list) { // ConcurrentModificationException
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
int n = iterator.next();
if(n % i == 0) {
iterator.remove();
}
}
}
The example above results in a ConcurrentModificationException. The condition to remove an element is, of course, just an example.
I'm sure I'm just missing something; but how should I construct a loop that achieves the same thing in Java without throwing an exception?
Obviously modifying list
when you iterate over it causing the execption.
You can use another list to maintain the list of elements to be removed and remove them at the end.
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
ArrayList<Integer> del = new ArrayList<Integer>(); // Elements to be deleted
for(int i : list) { // ConcurrentModificationException
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
int n = iterator.next();
if(n % i == 0) {
del.add(n);
}
}
}
list.removeALL(del);
Make the outer iteration iterate over a copy of the list.
for (int i : new ArrayList<>(list)) {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
int n = iterator.next();
if (n % i == 0) {
iterator.remove();
}
}
}
You are getting ConcurrentModificationException
because, while doing for
loop you are trying to modify the list
.
I am not sure whether following is elegant solution or not, but something like below may work:
Iterator<Integer> iterator = list.iterator();
int i=1;
while (iterator.hasNext()) {
int n = iterator.next();
if (n % i == 0) {
iterator.remove();
}
i++;
}
You cannot remove an item from a list that is being iterated. One option is to add the items that you need to another list. Finally you have list with the items you need. Or you can iterate over the clone of your original list.
i do some thing pretty similar to you. hav e alook at this code .
out:for(int h=0; h<tempAl.size(); h++) {
if(tempAl.get(0).split("\\s")[0].equals("OFF")){
tempAl.remove(0);
h=-1;
continue;
}
if(tempAl.get(h).split("\\s")[0].equals("ON")){
ONTime= tempAl.get(h);
///rest fof the code
}
i think you could also change the index after removing element from the arraylist.
I haven't tried, but either use:
List<Integer> list = new ArrayList<Integer>();
// add some values to it
for(Iterator<Integer> iterator1 = list.iterator(); iterator1.hasNext();) {
int i = iterator1.next();
for(Iterator<Integer> iterator2 = list.iterator(); iterator2.hasNext();){
int n = iterator.next();
if(n % i == 0) {
iterator2.remove();
}
}
}
or if this still throws the ConcurrentModificationException (I'm not sure what happens if you use 2 iterators backed by the same list), then use:
List<Integer> list = new ArrayList<Integer>();
// add some values to it
for(int i : new ArrayList(list)){ // copy list
...
}
foreach
java syntax hides an iterator but as hiding it, it is not possible to call remove
method on this one.
So I would do:
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
int count = 0;
for(Iterator<Integer> it = list.iterator();it.hasNext();count++){ //increments count++
Integer currentInt = it.next();
if(currentInt % count == 0){
it.remove();
}
}
You can see that the same feature is achieved without the need of a secondary iterator.
You can't iterate through the same list in the same time.
To sum up, a modcount
variable is used to detect unexpected change of itself everytime a list is parallely changed or iterated over.
Leading thus to a ConcurrentModificationException
.
It appears very often with multithreaded environment and developers must be aware of it.
Furthermore, prefer use for
loop instead while
loop to iterate over a collection.
Why ?
Because with the while
way, you let the iterator object still in scope after the loop whereas with for
, it doesn't. A simple ackward call to it.next()
would end up with a NoSuchElementException
.
It is a best practice to keep ;)