Java ArrayList并发修改

时间:2011-11-06 13:42:32

标签: java arraylist

我遇到了一些问题,因为我的方面很好地完成了这项工作:

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

我试图在没有复制mylist的情况下越来越多地获得一种优雅的方式...

2 个答案:

答案 0 :(得分:6)

目前的代码是:

  • 在外循环的第一次迭代中:
    • 删除第一个元素。
    • 在第一个内部循环中,将第一个元素(我们刚刚删除)中不是“==”的所有其他元素删除
    • 如果我们删除了超过2个元素,请将它们全部放在其他位置。
    • 否则将元素放回列表的末尾。

显然,这会在外部循环的第二次迭代中进行并发修改,因为内部循环已修改了您在外部循环中迭代的集合。你不能这样做。

但更重要的是,该算法没有多大意义。在我看来,这很可能意味着代码没有按照你的意图去做。除非您解释实际上尝试实现的目标,否则我们无法弄清楚真正的问题是什么,以及如何解决它。


我仍然不完全理解你想要实现的目标,但我认为该解决方案将涉及以下一个或两个:

  • myList的实现类更改为 允许并发修改的并发集合类之一;例如ConcurrentLinkedDeque

  • 用这个替换外部循环:

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

后一种补救措施摆脱了ConcurrentModificationException ,只要在第一个内部循环运行时没有其他任何东西修改列表。第一个补救措施完全摆脱ConcurrentModificationException,除了不能保证第一个内部循环会看到其他地方添加的元素。

在任何一种情况下,如果在处理条目时没有取得进展,你必须担心如何终止循环。

“大O”复杂性也是一个问题,但如果不了解“其他条件”正在做什么,就不可能进行表征。

答案 1 :(得分:1)

我假设您收到了ConcurrentModificationException。

当迭代器迭代时,你无法修改迭代器中的列表。

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