Nested iterating through list followed by an event

2019-05-06 13:11发布

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?

7条回答
▲ chillily
2楼-- · 2019-05-06 13:28

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++;
            }
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-05-06 13:28

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.

查看更多
成全新的幸福
4楼-- · 2019-05-06 13:29

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.

查看更多
来,给爷笑一个
5楼-- · 2019-05-06 13:30

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();
    }

  }

}
查看更多
不美不萌又怎样
6楼-- · 2019-05-06 13:31

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 ;)

查看更多
不美不萌又怎样
7楼-- · 2019-05-06 13:48

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);
查看更多
登录 后发表回答