由于增强的for循环而导致的concurrentmodification错误

e7arh2l6  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(357)

下面的代码导致 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);

    }
vql8enpb

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亿-这取决于你想做什么。

相关问题