我正在尝试为模拟WaTor编写代码,其中鲨鱼和鱼互相吃掉并模拟群体控制等。无论如何,我遇到的问题是即使使用迭代器我仍然会得到一个concurrect修改异常。
这是我的代码:
private void updateSharks() {
for(Iterator<Shark> sharkit = sharks.iterator(); sharkit.hasNext();) {
Shark sharky = sharkit.next();
if(sharky.hasStarved()) {
sharkit.remove();
}
else if(sharky.canBreed()) {
addNewShark(sharky.getX(),sharky.getY());
}
moveShark(sharky);
}
}
以下是例外:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at WaTor.Ocean.updateSharks(Ocean.java:281)
at WaTor.Ocean.update(Ocean.java:307)
at WaTor.Main.main(Main.java:13)
海洋中的第281行是“Shark sharky = sharkit.next();”谢谢你的帮助!
答案 0 :(得分:2)
在遍历列表时无法修改列表。 如果您在遍历时从列表中删除元素 - 修复它的一个选项是将这些元素放在另一个列表中,然后循环遍历该列表以删除元素。 - 其他选项是使用Iterator.remove() 您正在使用Iterator.remove()。这很好。
如果您在遍历时添加元素也可能是个问题。我还没有测试过您的代码。但请确保您没有在方法addNewSharks()和moveSharks()
中向列表鲨鱼添加元素答案 1 :(得分:0)
请查看Iterator的JavaDoc。对于remove
方法,您可以找到以下文本:
从底层集合中移除此迭代器返回的最后一个元素(可选操作)。每次调用next()时,只能调用此方法一次。如果在迭代正在进行的过程中以除了调用ths方法之外的任何方式修改底层集合,则未指定迭代器的行为。
对我来说,看起来你正在迭代它时向集合中添加元素。因此,您可能会遇到未指定的行为。
答案 2 :(得分:0)
正如其他人提到的,你不能在迭代时修改集合(删除是可选的)。好吧,你可以收集所有应该死在另一个集合中的鲨鱼,并在迭代器循环结束后删除它们。
尝试以下方法:
private void updateSharks() {
ArrayList<Shark> toRemove = new ArrayList<Shark>();
ArrayList<Shark> toAdd = new ArrayList<Shark>();
for(Iterator<Shark> sharkit = sharks.iterator(); sharkit.hasNext();) {
Shark sharky = sharkit.next();
if(sharky.hasStarved()) {
toRemove.add(sharky);
}
else if(sharky.canBreed()) {
toAdd.add(/*create new shark object here*/)
}
moveShark(sharky);
}
for (Shark shark : toRemove) {
sharks.remove(shark);
}
for (Shark shark: toAdd) {
sharks.add(shark);
}
}
编辑:工作原理
您正在遍历该集合。在此步骤中,您可以在集合中包含的对象中执行任何操作,但是您无法更改集合本身,因为迭代器不允许您这样做。
所以你创建了第二个临时集合。每次遇到要从主集合中删除的对象时,都会将此对象添加到临时集合中。因为在Java中只传递引用,并且此处没有深度复制,并且它是同时包含在两个集合中的同一对象。
现在,当迭代结束时,您拥有临时集合中包含的所有对象(或其引用,如果您更愿意这样考虑)。因为迭代器已经消失,所以没有任何东西限制你从主集合中删除所有这些对象,并且很容易完成!
答案 3 :(得分:0)
不要使用迭代器。像这样向后迭代集合:
import java.util.ArrayList;
public class RemoveFromCollectionExample {
//
// instance variables
//
private ArrayList<Shark> sharks;
//
// main
//
public static void main(String[] args) {
RemoveFromCollectionExample example = new RemoveFromCollectionExample();
example.sharks = new ArrayList<RemoveFromCollectionExample.Shark>();
example.addShark(false, false, 0, 0);
example.addShark(false, false, 0, 0);
example.addShark(false, false, 0, 0);
example.addShark(false, false, 0, 0);
example.addShark(false, false, 0, 0);
example.addShark(false, false, 0, 0);
example.addShark(false, true, 0, 0);
example.addShark(true, false, 0, 0);
example.addShark(true, false, 0, 0);
example.addShark(true, false, 0, 0);
System.out.println("START WITH: " + example.sharks.size());
example.updateSharks();
System.out.println("Added 1, Removed 3");
System.out.println("ENDED WITH: " + example.sharks.size());
}
//
// update sharks
//
private void updateSharks() {
for (int i = this.sharks.size() - 1; i > 0; i--) {
Shark sharky = this.sharks.get(i);
if (sharky.hasStarved()) {
this.sharks.remove(i);
System.out.println("REMOVED");
} else if (sharky.canBreed()) {
addNewShark(sharky.getX(), sharky.getY());
System.out.println("ADDED");
}
moveShark(sharky);
}
}
//
// add new shark method
//
private void addNewShark(int x, int y) {
this.sharks.add(new Shark(false, false, x, y));
}
private void addShark(boolean hasStarved, boolean canBreed, int x, int y) {
this.sharks.add(new Shark(hasStarved, canBreed, x, y));
}
//
// move method
//
private void moveShark(Shark sharky) {
}
//
// Shark class
//
private class Shark {
private boolean hasStarved;
private boolean canBreed;
private int x;
private int y;
public boolean hasStarved() {
return hasStarved;
}
public void setHasStarved(boolean hasStarved) {
this.hasStarved = hasStarved;
}
public boolean canBreed() {
return canBreed;
}
public void setCanBreed(boolean canBreed) {
this.canBreed = canBreed;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Shark(boolean hasStarved, boolean canBreed, int x, int y) {
super();
this.hasStarved = hasStarved;
this.canBreed = canBreed;
this.x = x;
this.y = y;
}
public void moveShark() {
}
}
}