Java 由于增强的for循环而导致ConcurrentModification错误
下面的代码导致线程“main”java.util.ConcurrentModificationException中出现异常 我正在尝试使用一个增强的for循环来迭代我的无人机阵列列表,以更新它们的位置和方向。以下代码仅适用于ArrayList中的1个无人机Java 由于增强的for循环而导致ConcurrentModification错误,java,for-loop,arraylist,Java,For Loop,Arraylist,下面的代码导致线程“main”java.util.ConcurrentModificationException中出现异常 我正在尝试使用一个增强的for循环来迭代我的无人机阵列列表,以更新它们的位置和方向。以下代码仅适用于ArrayList中的1个无人机 tryToMove()获取无人机的方向,将其移动到相应的x、y位置,并检查其是否有效,如果无效,则改变方向 doDisplay()使用控制台中的无人机打印竞技场 public static void moveAllDrones(){
tryToMove()
获取无人机的方向,将其移动到相应的x、y位置,并检查其是否有效,如果无效,则改变方向
doDisplay()
使用控制台中的无人机打印竞技场
public static void moveAllDrones(){
String strOfCurrentDirection;
Direction currentDirection;
for (String drone : drones) {
id = drones.indexOf(drone);
System.out.println("Working on drone: " + id);
String[] coords = drone.split(",");
accX = Integer.parseInt(coords[0]);//get x coordinate
accY = Integer.parseInt(coords[1]);// get y coordinate
String droneWithCurrentID = drones.get(id); //direction in string
strOfCurrentDirection = droneWithCurrentID.split(",")[2];
currentDirection = Direction.valueOf(strOfCurrentDirection); //convert string to direction
Drone.tryToMove(id, currentDirection, accX, accY);
}
DroneInterface.doDisplay();
}
我不知道为什么这个增强的for循环只适用于1架无人机。
谢谢你的帮助
更新:
public static void tryToMove(int id2, Direction accDir, int x1, int y1) {
xPos = x1;
yPos = y1;
//Direction d = Drone.direction; // get current direction drone is facing.
System.out.println("Trying to move drone, "+id2+ ". In the direction of: "+accDir);
switch (accDir) {
case NORTH:
yPos -= 1;
if (DroneArena.canMoveHere(xPos, yPos)) {
DroneArena.yRan = yPos;
} else {
yPos += 1;
accDir = Direction.nextDirection();
}
DroneArena.updateDrone(id2, accDir, xPos, yPos);
break;
case EAST:
xPos += 1;
if (DroneArena.canMoveHere(xPos, yPos)) {
DroneArena.xRan = xPos;
} else {
xPos -= 1;
accDir = Direction.nextDirection();
}
DroneArena.updateDrone(id2, accDir, xPos, yPos);
break;
case SOUTH:
yPos += 1;
if (DroneArena.canMoveHere(xPos, yPos)) {
DroneArena.yRan = yPos;
} else {
yPos -= 1;
accDir = Direction.nextDirection();
}
DroneArena.updateDrone(id2, accDir, xPos, yPos);
break;
case WEST:
xPos -= 1;
if (DroneArena.canMoveHere(xPos, yPos)) {
DroneArena.xRan = xPos;
} else {
xPos += 1;
accDir = Direction.nextDirection();
}
DroneArena.updateDrone(id2, accDir, xPos, yPos);
break;
}
}
更新无人机:
public static void updateDrone(int id2, Direction direction, int newX, int newY){
updatedDirection = direction;
DroneArena.direction = updatedDirection;
drones.remove(id2);
drones.add(id2, newX + "," + newY +"," + updatedDirection);
}
CoModEx意味着一件事,而且只意味着一件事:
for(ta:C)
正在创建一个C
的迭代器).remove()
方法)for(ta:c)
循环(您到达循环的末尾,或者在循环中运行continue;
)无人机
做一个迭代器,修改无人机
,然后你迭代循环(因为tryToMove
修改无人机)
你不能这么做,原因应该很明显:这到底是什么意思?如果你迭代[1,2,3,4,5]
在2
的迭代过程中,您删除了3
,那么3应该被跳过吗?如果在2
的迭代过程中,您删除了1
?如果3应该被跳过,但是1已经完成并且不能被跳过,这意味着什么?另外,尝试跟踪已删除的内容是非triv的ial(通常您只需要使用索引,但如果您在循环的中途开始删除早期的元素,这会变得很棘手),这也是为什么它会这样工作的第二个原因:在迭代集合时,您不能修改它
那么,你如何解决这个问题呢
最简单的方法是先复制无人机,然后在副本中迭代。这样,在循环过程中所做的任何修改都不会影响您的副本,因此不会导致共索引。请注意,这当然意味着您所做的任何修改在循环过程中都不可见
第二个选项(仅适用于基于索引的快速查找的ArrayList或其他构造)是使用旧样式的for循环,并手动管理索引变量
第三种方法是使用具有明确定义的行为的集合类型(例如CopyOnWriteArrayList
),它执行列表本身内置的第一个选项
第四种方法是重新设计您正在做的事情,以便修改基础集合不再是其中的一部分
第五种方法是在迭代过程中存储您希望对列表执行的所有操作,然后在迭代之后应用它们
还有10亿个-这取决于您尝试执行的操作。当您在对集合进行迭代时修改集合时,会抛出一个
ConcurrentModificationException
。您显示的代码不会修改无人机
集合,因此抛出ConcurrentModificationException
的原因必须在Drone.tryToMove()
是否修改Drone.tryToMove()
中的任何字符串?Drone
我们也需要查看该方法,以帮助您。@CharlieArmstrong`tryToMove()调用updateDrone()它删除具有相应id的arrayList,然后向列表中添加具有相同id但为new的新元素values@ThomasKläger将更新问题以显示方法好了,你在迭代ArrayList时修改了它。是相关文档。我通过谷歌搜索“Java ConcurrentModificationException”找到了它。如果StackOverflow不是那么禁忌的话,我会发布一个LMGTFY链接。我如何才能将其更改为循环的标准?我太远了,无法重新设计该方法,因为我的最后期限很近。非常遗憾。感谢您提供的详细答案。将ArrayList更改为CopyOnWriteArrayList将其排序…感谢您的帮助!