简体   繁体   中英

Java ArrayList concurrent modification

i'm getting some problem to get this work well as i aspect:

    for(Iterator<Object> i = mylist.iterator(); i.hasNext();) {
        Object obj = i.next();
        ArrayList<Object> newlist = new ArrayList<Object>();
        newlist.add(obj);
        i.remove();
        for(Iterator<Object> in = mylist.iterator(); in.hasNext();) {
            Object next = in.next();
            if (obj != next && (another condition)) {
                newlist.add(next);
                in.remove();
            }
        }
        if (newlist.size() > 2) anotheList.add(newlist);
        else for(Object r : newlist) {
            //mylist get back object:
            mylist.add(r);
        }
    }

I'm trying to get an elegant way to do that without copy mylist more and more times...

What the code is currently doing is this:

  • In the first iteration of the outer loop:
    • Remove the first element.
    • In the first inner loop, remove every other element that is not '==' to the first element (that we just removed)
    • If we removed more than 2 elements, put them all somewhere else.
    • Otherwise put the element back on the end of the list.

Obviously, this runs into a concurrent modification on the second iteration of the outer loop, because the inner loops have modified the collection that you are iterating in the outer loop. You can't do that.

But, more importantly, the algorithm doesn't make much sense. To my mind, that most likely means that the code is not doing what you intend it to do. Unless you explain what you are actually trying to achieve, we can't figure out what the real problem is, and how to fix it.


I still don't exactly understand what you are trying to achieve, but I think that the solution is going to involve one or both of the following:

  • Change the implementation class of myList to one of the concurrent collection classes that does allow concurrent modification; eg ConcurrentLinkedDeque .

  • Replace the outer loop with this:

     while (!myList.isEmpty()) { Object obj = myList.remove(0); ... } 

The latter remedy gets rid of the ConcurrentModificationException provided that nothing else modifies the list while the first inner loop is running . The first remedy gets rid of the ConcurrentModificationException entirely, except that there is no guarantee that the first inner loop will see elements added elsewhere.

In either case, you have to worry about how to terminate the loop if it makes no progress in processing the entries.

The "big O" complexity is also a concern, but it is not possible to characterize without understanding what the "other condition" is doing.

I assume you get a ConcurrentModificationException.

You can't modify the list in an iterator while a second one is iterating over it.

http://download.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html

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