处理中的ConcurrentModificationException

时间:2018-04-16 21:56:54

标签: java processing

我尝试将ArrayList实现为我正在制作的内容,但无论何时我在循环中向ArrayList添加新项目,我都会得到ConcurrentModificationError 1}},这是有道理但我不知道如何解决这个问题。

我的代码如下所示:

ArrayList<Pipe> pipes;

void setup() {
  size(640, 360);
  pipes = new ArrayList<Pipe>();
  make();
}
void make() {
  pipes.add(new Pipe());
  Pipe P = pipes.get((pipes.size()-1));
  P.create();
}

void draw() {
  background(255);
  for (Pipe p : pipes) {
    p.display();
    p.move();
    if (p.x < 3*width/4) {
      make();
      println("A");
    }  
  }
}

错误肯定不是来自它自己的对象,并且在draw()中调用make()函数时会发生错误。

非常感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:1)

使用ListIterator进行迭代并添加到列表中。

for (ListIterator<Pipe> iter = pipes.listIterator(); iter.hasNext();) {
    Pipe p = iter.next();
    [...]
    make(iter);
}

然后在make:

iter.add(new Pipe());

来自ListIterator的javadoc:

  

列表的迭代器,允许程序员在任一方向遍历列表,在迭代期间修改列表,并获取迭代器在列表中的当前位置。

您可以添加到迭代器,而不是添加到列表中。在这种情况下没有并发修改,因为迭代器能够跟踪列表更改。

请注意,iter.add()调用会在iter.next()返回的元素之前添加元素。这意味着新添加的对象不会是列表中的最后一个。这通常是首选,因为您不希望干扰循环的前向流,即您不希望循环的下一次迭代在新添加的对象上。但是你的情况可能会有所不同。

答案 1 :(得分:1)

我建议您使用CopyOnWriteArrayList

这将允许列表中的突变,同时通过生成基础数组的副本来保留迭代器的完整性。

当然,这会带来性能成本。

尝试一下(我扼杀了你没有提供实现的方法):

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class Test {
    private int width;

    private class Pipe {
        public int x;
        public void display() {
        }
        public void move() {
        }
        public void create() {
        }
    }

    List<Pipe> pipes;

    void size(int w, int h) {
    }

    public void background(int i) {
    }

    void setup() {
        size(640, 360);
        pipes = new CopyOnWriteArrayList<Pipe>();
        make();
    }

    void make() {
        pipes.add(new Pipe());
        Pipe P = pipes.get((pipes.size() - 1));
        P.create();
    }

    void draw() {
        background(255);
        for (Pipe p : pipes) {
            p.display();
            p.move();
            if (p.x < 3 * width / 4) {
                make();
                System.out.println("A");
            }
        }
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.setup();
        t.draw();
    }
}