我有一个涉及一个ArrayList,2个Iterators和一些嵌套for循环的快速问题。我试图使用多个重力井相互拉动并移动来制造一些重力引擎。为此,Iv制作了这些重力井的ArrayList,随机放置在屏幕上随机放置。这里仅供参考。
for(int i = 0; i < amount; i++){ // makes all
int mass = rand.nextInt(45,65);
int locX = rand.nextInt(50, getWidth()-100);
int locY = rand.nextInt(50, getHeight()-100);
Color cColor = rand.nextColor();
if(mass%8==0){
mass = rand.nextInt(25,35);
}
else if(mass%7==0){
mass = rand.nextInt(75,85);
}
Body body = new Body((double)locX,(double)locY,mass);
body.setFilled(true);
body.setColor(Color.WHITE);
body.setFillColor(cColor);
add(body);
bodys.add(body);
}
bodys是包含所有内容的ArrayList的名称。所以我真正的问题来自迭代器。下面是给我带来麻烦的代码:
public void move(){
Iterator<Body> eIter = bodys.iterator();
while(eIter.hasNext()){ // finding the thing we edit
Body edit = eIter.next();
int addX = 0, addY = 0;
int totalX = 0, totalY = 0;
double ex = edit.getX(), ey = edit.getY();
double eMass = edit.getMass(), eSize = edit.getHeight();
double eMoveX = edit.getMoveX(), eMoveY = edit.getMoveY();
int placeInArrayEdit = bodys.indexOf(edit);
Iterator<Body> fIter = bodys.iterator();
while(fIter.hasNext()){ // iterating through the force pulling the edit body
Body force = fIter.next(); /// ConcurrentModificationException is thrown
int placeInArrayForce = bodys.indexOf(force);
if(placeInArrayForce != placeInArrayEdit){ // making sure the 2 bodys arent the same
double fx = force.getX(), fy = force.getY();
double fMass = force.getMass();
double fMoveX = force.getMoveX(), fMoveY = force.getMoveY();
double difX = (ex-fx);
double difY = (ey-fy);
double distX = distanceP(ex, fx);
double distY = distanceP(ey, fy);
double vecX = (difX/distX);
double vecY = (difY/distY);
if(distance(fx,ex,fy,ey) <= eSize/3){ // if they are colliding
if(eMass >= fMass){
remove(edit);
edit.addMass((int)(fMass));
eIter.remove(); // problem
}
if(eMass < fMass){
remove(force);
force.addMass((int)(eMass));
fIter.remove();
}
}
double grav = (eMass/fMass);
grav -= (grav*.50);
addX -= (vecX/grav)/2; // this determines movement which means i
addY -= (vecY/grav)/2; // need to edit this with fMass
}
edit.setVelX(addX/(eMass + (eMass*.75)));
edit.setVelY(addY/(eMass + (eMass*.75)));
edit.addMoveX(edit.getVelX());
edit.addMoveY(edit.getVelY());
edit.move(edit.getMoveX(),edit.getMoveY());
}
}
}
上面的代码是移动重力井并测试碰撞。问题是引发了ConcurrentModificationException,其中iv表示要抛出它。
我花了大约一个小时左右的时间寻找解决方案,没有尝试过任何尝试。代码一直工作直到井实际相互碰撞,然后抛出错误。有没有办法避免这个错误,同时仍然像这样测试碰撞,或者我的代码太破了?
感谢您的帮助!如果您需要澄清任何内容,请告诉我,因为这是我在StackOverflow上的第一个问题
答案 0 :(得分:4)
请参阅ArrayList
的javadoc:
此类
iterator
和listIterator
方法返回的迭代器是 fail-fast :如果列表在结构上经过修改后的任何时间除了通过迭代器自己的remove
或add
方法之外,以任何方式创建迭代器,迭代器将抛出ConcurrentModificationException
。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来不确定的时间冒着任意的,非确定性行为的风险。
因此,您有2个迭代器:外部循环为eIter
,内循环为fIter
。
当您致电eIter.remove()
时,fIter
会变坏
当您致电fIter.remove()
时,eIter
会变坏
(如果你曾调用bodys.remove(index)
,两者都会变坏。)
无论哪种方式,其中一个迭代器将过时,并在您调用ConcurrentModificationException
时抛出next()
。
另外,当你打电话给eIter.remove()
时,你不会突破内循环,所以你冒着尝试在内循环的另一次迭代中再次做这件事的风险。
简而言之,您需要找到另一种方式,例如使用索引和get(index)
调用,或类似的东西。