Java 处理中的ConcurrentModificationException
我试图在我正在制作的东西中实现一个Java 处理中的ConcurrentModificationException,java,processing,Java,Processing,我试图在我正在制作的东西中实现一个ArrayList,但是每当我从循环中向ArrayList添加一个新项目时,我会得到一个ConcurrentModificationError,这很有意义,但我不知道如何解决这个问题 我的代码如下所示: ArrayList<Pipe> pipes; void setup() { size(640, 360); pipes = new ArrayList<Pipe>(); make(); } void make() { p
ArrayList
,但是每当我从循环中向ArrayList
添加一个新项目时,我会得到一个ConcurrentModificationError
,这很有意义,但我不知道如何解决这个问题
我的代码如下所示:
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");
}
}
}
ArrayList管道;
无效设置(){
尺寸(640360);
管道=新的ArrayList();
make();
}
使无效{
管道。添加(新管道());
pipep=pipes.get((pipes.size()-1));
P.创建();
}
作废提款(){
背景(255);
用于(管道p:管道){
p、 显示();
p、 move();
如果(p.x<3*宽度/4){
make();
println(“A”);
}
}
}
错误肯定不是来自对象本身,错误发生在draw()中调用make()函数时
任何帮助都将不胜感激,谢谢。使用a进行迭代并添加到列表中
for (ListIterator<Pipe> iter = pipes.listIterator(); iter.hasNext();) {
Pipe p = iter.next();
[...]
make(iter);
}
for(ListIterator iter=pipes.ListIterator();iter.hasNext();){
管道p=iter.next();
[...]
make(iter);
}
然后在制造中:
iter.add(新管道())代码>
从列表迭代器的javadoc中:
列表的迭代器,允许程序员沿任意方向遍历列表,在迭代过程中修改列表,并获取迭代器在列表中的当前位置
您将添加到迭代器,而不是添加到列表中。在这种情况下没有并发修改,因为迭代器能够跟踪列表更改
请注意,iter.add()
调用将在iter.next()
返回的元素之前添加元素。这意味着新添加的对象不会是列表中的最后一个对象。这通常更可取,因为您不希望干扰循环的正向流,即不希望循环的下一次迭代在新添加的对象上。但您的情况可能会有所不同。使用a进行迭代并添加到列表中
for (ListIterator<Pipe> iter = pipes.listIterator(); iter.hasNext();) {
Pipe p = iter.next();
[...]
make(iter);
}
for(ListIterator iter=pipes.ListIterator();iter.hasNext();){
管道p=iter.next();
[...]
make(iter);
}
然后在制造中:
iter.add(新管道())代码>
从列表迭代器的javadoc中:
列表的迭代器,允许程序员沿任意方向遍历列表,在迭代过程中修改列表,并获取迭代器在列表中的当前位置
您将添加到迭代器,而不是添加到列表中。在这种情况下没有并发修改,因为迭代器能够跟踪列表更改
请注意,iter.add()
调用将在iter.next()
返回的元素之前添加元素。这意味着新添加的对象不会是列表中的最后一个对象。这通常更可取,因为您不希望干扰循环的正向流,即不希望循环的下一次迭代在新添加的对象上。但是您的情况可能会有所不同。我建议您使用一种新的方法
这将允许对列表进行变异,同时通过创建底层数组的副本来保持迭代器的完整性
当然,这是以性能为代价的
尝试一下(我删除了您调用的方法,但没有提供实现):
import java.util.List;
导入java.util.concurrent.CopyOnWriteArrayList;
公开课考试{
私有整数宽度;
专用管道{
公共int x;
公共空间显示(){
}
公开作废动议(){
}
公共void create(){
}
}
列出管道清单;
空隙大小(整数w,整数h){
}
公共空间背景(int i){
}
无效设置(){
尺寸(640360);
管道=新的CopyOnWriteArrayList();
make();
}
使无效{
管道。添加(新管道());
pipep=pipes.get((pipes.size()-1));
P.创建();
}
作废提款(){
背景(255);
用于(管道p:管道){
p、 显示();
p、 move();
如果(p.x<3*宽度/4){
make();
系统输出打印项次(“A”);
}
}
}
公共静态void main(字符串[]args){
测试t=新测试();
t、 设置();
t、 draw();
}
}
我建议使用一个
这将允许对列表进行变异,同时通过创建底层数组的副本来保持迭代器的完整性
当然,这是以性能为代价的
尝试一下(我删除了您调用的方法,但没有提供实现):
import java.util.List;
导入java.util.concurrent.CopyOnWriteArrayList;
公开课考试{
私有整数宽度;
专用管道{
公共int x;
公共空间显示(){
}
公开作废动议(){
}
公共void create(){
}
}
列出管道清单;
空隙大小(整数w,整数h){
}
公共空间背景(int i){
}
无效设置(){
尺寸(640360);
管道=新的CopyOnWriteArrayList();
make();
}
使无效{
管道。添加(新管道());
pipep=pipes.get((pipes.size()-1));
P.创建();
}
作废提款(){
背景(255);
用于(管道p:管道){
p、 显示();
p、 move();
如果(p.x<3*宽度/4){
make();
系统输出打印项次(“A”);
}
}
}
公共静态void main(字符串[]args){
测试t=新测试();
t、 设置();
t、 draw();
}
}
您正在make
中添加一个新的pipe
,它使foreach
中使用的迭代器无效:如果编写pipe P=new pipe(),代码不是会更好/更明显/更清晰吗;白痢