下面的代码导致 Exception in thread "main" java.util.ConcurrentModificationException
错误。
我正在尝试使用一个增强的for循环来迭代我的无人机阵列列表,以更新它们的位置和方向。以下代码仅适用于arraylist中的1个无人机。 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);
}
1条答案
按热度按时间vql8enpb1#
comodex意味着一件事,而且只有一件事:
从集合c创建迭代器i(和
for (T a : c)
正在创建的迭代器c
).在稍后的某个时间点,集合c以某种方式被修改(而不是通过
.remove()
迭代器i的方法)。您可以以任何方式与i交互:调用其中的任何方法,或者点击
for (T a : c)
循环(你到达循环的末尾,或者跑continue;
在循环中。你在这里这样做:你做一个迭代器
drones
当您启动for循环并修改drones
,然后迭代循环(因为tryToMove
修改无人机)。你就是做不到这一点,原因应该很明显:这到底是什么意思?如果你反复
[1, 2, 3, 4, 5]
在迭代过程中2
,则删除3
,那么应该跳过3吗?如果在2
,则删除1
? 如果3应该跳过,但是1已经完成,不能跳过,这是什么意思?另外,尝试跟踪已删除的内容是非常重要的(通常您只需要使用索引,但如果您在循环的中途开始删除早期元素,这将变得很棘手),这也是为什么它会这样工作的第二个原因:您不能在遍历集合时修改它。句号。那么,你怎么解决呢?
最简单的方法是先制作一个无人机的副本,然后遍历副本。这样,您在循环过程中所做的任何修改都不会影响您的副本,因此不会导致共索引。请注意,这当然意味着在循环期间,您所做的任何修改都不可见。
第二个选项(仅适用于arraylists或其他基于索引的快速查找结构)是使用旧样式for循环,并手动管理索引变量。
第三种方法是将集合类型与显式定义的行为一起使用(例如
CopyOnWriteArrayList
,它执行列表本身内置的第一个选项。第四种方法是重新设计您正在做的事情,以便修改基础集合不再是其中的一部分。
第五种方法是在迭代过程中存储您希望对列表执行的所有操作,然后在迭代之后应用它们。
还有10亿-这取决于你想做什么。