简体   繁体   中英

Is possible to erase an ArrayList element inside a for( ) cycle?

I have this code:

outlets is a ArrayList passed to the method; riverBasin is a 2D "matrix" of int (int[][] riverBasin);

for (int[] item: outlets) {
    if (item[0] < 2 || item[0] > this.riverBasin.length - 1 || item[1] < 2 || item[1] > this.riverBasin[0].length - 1) {

        System.out.println("This provisionally substitutes error catching. Outlet (" + item[0] + "," + item[1] + ") is not correct.");
        outlets.remove(item);
        System.out.println("Remaining outlets: ");
        for (int[] atem: outlets) {
            System.out.print("(" + atem[0] + "," + atem[1] + ")\n");
        }
    }
    else {
        this.riverBasin[item[0]][item[1]] = 10;
    }
}

removing the "item" from the ArrayList outlets generate an error:

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 org.geoframe.ocn.Eden.setMultipleOutlet(Eden.java:135)
    at org.geoframe.ocn.Eden.main(Eden.java:205)

which I do not really completely understand. I suspect, however, that I broke the iterator. Correct ? How could then I remove the unwanted elements in the ArrayList.

Thank you in advance for any help,

riccardo

You should Iterate the ArrayList using the Iterator. Then use the Iterator's remove method.

You need to explicitly use an iterator and call remove().

final Iterator<int[]> iterator = outlets.iterator();
while (iterator.hasNext()) {
    final int[] item = iterator.next();
    ....
    if (...) {
        iterator.remove();
    }
}

you cannot remove by using "for each" loop. You can use Iterator instead of it.

for (int[] item: outlets) {}

This is an advanced for loop. Internally it does the same thing as creating an iterator of the collection and iterating over it. But if you explicitly don't get an Iterator object you loose the capability of removing elements from collection because if you try to remove an element from the collection while iterator is iterating on it you will always get java.util.ConcurrentModificationException .

So in your case get an iterator by outlets.iterator(); and use it's remove method iterator.remove(); .

It is better to use advanced loop for read operations only.

The exception you are facing because of Fail-fast behaviour of itreator . The advance for loop Ie for each, will create a itreator for you, which always checks the original size with the current size, when miss match happens it will through you exception.

As per your question, you can remove Arraylist element using for each,
1- you have get the index(s) or element(s) to be removed and outside of your loop remove it.

2- sample:

for(int i=0;i < l.size() ; i++){
   //some condtions to check the element
   //if you want to delete this element or index
   l.remove(i); or l.remove(l.get(i));
}

ps here l is List you have.

But as always suggested, it's a good practice to do such operation using a itreator remove method.

You will have to delete the entry via the iterator. This means you cannot use the enhance fore loop.

Try:

for(Iterator<int[]> outletsIterator = outlets.iterator(); outletsIterator.hasNext();){
    int[] item = outletsIterator.next();

    ...

    outletsIterator.remove();
}

Note: It's not recommended to mix generics and arrays. Consider to use: List<List<Integer>>

You are not allowed to remove the items directly from a collection while iterating over it. To solve your problem use any one of the below solutions:

  1. Use iterate() method of Collection interface to get an Iterator representing

    your collection, then iterate through it and remove desired items from your iterator

  2. Use iterate() method of Collection interface to get an Iterator representing your

    collection, then iterate through it and mark the desired items you want to remove by copying their

    references in a new collection object. Then after the iteration completes,

    call remove(Collection c)

    method to remove desired items from your Collection object(Something like copy desired items from

    your list by iterating it to a new list and after iteration call method as:

    your_list_object.remove(new_list_object) for more detail see here )

Source: https://stackoverflow.com/questions/2513509/how-to-remove-concurrentmodificationexception

There're already posted some similar questions and answers:

  1. You can keep track of the indexes of the items you want to remove, and then remove them after you are done iterating.
  2. Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.

Source: Getting a ConcurrentModificationException thrown when removing an element from a java.util.List during list iteration? (hvgotcodes)

  1. Use the toArray() function on your ArrayList outlets, do the iteration on the array and delete from your ArrayList outlets.

there are already many comments here that solves your problem. I can rather see possible potential problems in the code. For example why are you putting if check in the loop if it is going to deal only with index 0 and 1. So you even need not to iterate and delete elements. And for the solutions yes iterator is one way of doing this but I would rather prefer to use google collection APIs for this. example of such call is

Iterables.filter(yourCollectionToBeFiltered, predicate)

more you can explore on https://code.google.com/p/guava-libraries/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM