从 arraylist 中删除对象正在做奇怪的事情

remove objects from arraylist is doing strange things

在下面的代码中,我希望球从 ArrayList ballList 变为另一个 ArrayList oldBalls,只要它们的年龄高于阈值。

这段代码应该很简单,但我不明白为什么当年龄与阈值相同(不是更大)时它们消失然后在 2 帧后返回。

我已经在 java 中使用 ArrayLists 的迭代器检查了相关问题,但我认为应该有一种方法可以在没有 java 的情况下进行处理。 另外,我似乎无法 post 在处理论坛上提出任何问题,即使我可以登录,也不知道为什么...

我已将代码减少到能够重现错误的最低限度。

ArrayList <Ball> ballList;
ArrayList <Ball> oldBalls;
int threshold=4;
PFont font;

void setup(){
 size(400,400);
 frameRate(0.5);
 font=createFont("Georgia", 18);
 textFont(font);
 textAlign(CENTER, CENTER);
 ballList=new ArrayList<Ball>();
 oldBalls=new ArrayList<Ball>();
 noFill();
 strokeWeight(2);
}

void draw(){
  background(0);
  Ball b=new Ball(new PVector(10, random(height/10,9*height/10)),new PVector(10,0),0);
  ballList.add(b);

  stroke(0,0,200);
  for(int i=0;i<oldBalls.size();i++){
    Ball bb=oldBalls.get(i);
    bb.update();
    bb.render();
    text(bb.age,bb.pos.x,bb.pos.y);
  }

  stroke(200,0,0);
  for(int i=0;i<ballList.size();i++){
    Ball bb=ballList.get(i);
    bb.update();
    bb.render();
    bb.migrate();
    text(bb.age,bb.pos.x,bb.pos.y);
  }
}

class Ball{
  PVector pos;
  PVector vel;
  int age;

  Ball(PVector _pos, PVector _vel, int _age){
    pos=_pos;
    vel=_vel;
    age=_age;
  }

  void migrate(){
    if(age>threshold){
      oldBalls.add(this);
      ballList.remove(this);
    }
  }

  void update(){
    pos.add(vel);
    age+=1;
  }

  void render(){
    ellipse(pos.x,pos.y,24,24);
  }
}

注意标有 age=threshold 的球是如何突然消失的...

我猜问题出在这里:

for(int i=0;i<ballList.size();i++){
    Ball bb=ballList.get(i);
    bb.update();
    bb.render();
    //add this
    if(bb.migrate())
        i--;
    text(bb.age,bb.pos.x,bb.pos.y);
}

boolean migrate(){
    if(age>threshold){
      oldBalls.add(this);
      ballList.remove(this);
      //and this
      return true;
    }
    return false;
}

migrate() 将从 ballList 中删除对象并将其大小减小 1。

这里看起来像是因为您在遍历列表的同时更改列表。考虑一下你在这里的这个 for 循环

  for(int i=0;i<ballList.size();i++){
    Ball bb=ballList.get(i);
    bb.update();
    bb.render();
    bb.migrate();
    text(bb.age,bb.pos.x,bb.pos.y);
  }

假设 ballList 中有 2 个球都是 3 岁,第一个循环获取 ball[0] 然后将其从列表中删除,我将递增并且循环将立即退出,因为 ballList.size() 是现在 1. 所以不是到达 4 岁的球消失了,而是随后的球消失了。