Java 在两个位置循环通过LinkedLinkst会产生错误

Java 在两个位置循环通过LinkedLinkst会产生错误,java,linked-list,iteration,Java,Linked List,Iteration,所以我在用Java做一个小游戏,在这个游戏中,你有存储在LinkedList中的实体。在tick方法中,我遍历实体的LinkedList,如下所示: @Override public void tick(float delta) { for (Entity e : entities) { e.tick(delta); } player.tick(delta); } 渲染方法也是如此 @Override public void render(Graphic

所以我在用Java做一个小游戏,在这个游戏中,你有存储在LinkedList中的实体。在tick方法中,我遍历实体的LinkedList,如下所示:

@Override
public void tick(float delta) {
    for (Entity e : entities) {
        e.tick(delta);
    }
    player.tick(delta);
}
渲染方法也是如此

@Override
public void render(Graphics g) {
    g.setColor(Color.DARK_GRAY);
    g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
    for(Entity e : entities) {
        e.render(g);
    }
    player.render(g);
}
其中一个实体是名为Block的类。在Block类中,有一个函数,如果一个块在附近,它会返回,在这个函数中,我也会遍历实体的LinkedList,它是从Block中的以下tick方法调用的:

    @Override
public void tick(float delta) {
    if (color == Color.WHITE) {
        if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
            if (getSurrounding(-32, -32).getStrength() < strength) {
                getSurrounding(-32, -32).setStrength(-50);
            }
        }
    }

    if (!inGame.entities.isEmpty() && strength <= 0) {
        inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
    }
}

public Block getSurrounding(int xOffset, int yOffset) {
    for (Entity e : inGame.entities) {
        if (e instanceof Block) {
            if (x + xOffset == e.getX() && y + yOffset == e.getY()) {
                return (Block) e;
            }
        }
    }
    return null;
}
(前两个代码示例位于InGame.java文件中,第36行是tick方法中的for循环) 现在如何停止此错误?

通常与在循环中迭代列表时修改列表有关

我的假设是,在迭代过程中删除一个元素

为了防止这种情况发生,我建议在循环中(并且满足某些条件)保存要删除的对象,然后在循环完成后将其从列表中删除

编辑:根据更新的问题,您正在删除勾选方法中的元素。我不会在这里这样做,而是返回要删除的元素,并且仅当不再迭代要从中删除的列表时才将其删除

可能的解决方案: 我将创建另一个方法来检查实体的强度,并从tick方法调用该方法(这是为了保存tick方法,该方法必须返回要删除的对象),如下所示:

在实体类中:

public boolean checkStrength(){
    if (!inGame.entities.isEmpty() && strength <= 0) {
        return true;
    }
    return false;
}
public boolean checkStrength(){
if(!inGame.entities.isEmpty()&&strength通常与在循环中遍历列表时修改列表有关

我的假设是,在迭代过程中删除一个元素

为了防止这种情况发生,我建议在循环中(并且满足某些条件)保存要删除的对象,然后在循环完成后将其从列表中删除

编辑:根据更新的问题,您正在删除tick方法中的一个元素。我不会在这里执行此操作,而是返回您要删除的元素,并且仅当您不再迭代要从中删除的列表时才将其删除

可能的解决方案: 我将创建另一个方法来检查实体的强度,并从tick方法调用该方法(这是为了保存tick方法,该方法必须返回要删除的对象),如下所示:

在实体类中:

public boolean checkStrength(){
    if (!inGame.entities.isEmpty() && strength <= 0) {
        return true;
    }
    return false;
}
public boolean checkStrength(){

如果(!inGame.entities.isEmpty()&&strength您正在
tick()
方法中删除实体…而在该方法中,您仍在外部tick方法中迭代实体…因为您正在修改
e.tick()中的列表
,列表正在更改,这将导致下一次迭代失败…用内联方法替换对
e.tick()
的方法调用将更清楚地说明问题:

@Override
public void tick(float delta) {
    for (Entity e : entities) {
        //e.tick(delta); --inline below

          if (color == Color.WHITE) {
              if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
                  if (getSurrounding(-32, -32).getStrength() < strength) {
                      getSurrounding(-32, -32).setStrength(-50);
                  }
              }
          }

          if (!inGame.entities.isEmpty() && strength <= 0) {
              inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
          }
      }

}

您正在删除
tick()
方法中的实体…而在该方法中,您仍在迭代外部tick方法中的实体…因为您正在修改
e.tick()
中的列表,列表正在更改,这会导致下一次迭代失败…替换对
e.tick()的方法调用
使用内联方法可以更清楚地说明问题:

@Override
public void tick(float delta) {
    for (Entity e : entities) {
        //e.tick(delta); --inline below

          if (color == Color.WHITE) {
              if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
                  if (getSurrounding(-32, -32).getStrength() < strength) {
                      getSurrounding(-32, -32).setStrength(-50);
                  }
              }
          }

          if (!inGame.entities.isEmpty() && strength <= 0) {
              inGame.entities.remove(this); // <------ REMOVING AN ELEMENT
          }
      }

}

使用迭代器的解决方案:

将第一个代码块替换为以下代码块:

public void tick(float delta) {
    for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
      boolean remove = e.tick(delta);
      if(remove) {
          iterator.remove();
      }
    }
    player.tick(delta);
}

这应该可以解决您的问题。方法返回类型必须更改,以便我们有一个指示器,指示何时删除任何元素,何时不删除。每次
勾选
返回true时,相应的元素将被删除

使用迭代器的解决方案:

将第一个代码块替换为以下代码块:

public void tick(float delta) {
    for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
      boolean remove = e.tick(delta);
      if(remove) {
          iterator.remove();
      }
    }
    player.tick(delta);
}


这应该可以解决您的问题。方法返回类型必须更改,以便我们有一个指示器,指示何时删除任何元素,何时不删除。每次
勾选
返回true时,相应的元素将被删除

在迭代时不要从列表中删除元素。@hellzone不完全为true。如果他使用
迭代器
,它将work@hellzone海报似乎没有删除anything@hellzone我只是在迭代后删除块的tick方法中的元素,等等。所以这不是一个问题,对吗?显然是这样,否则你不会得到例外。在迭代元素时,不要从列表中删除元素。@hellzone这并不完全正确。如果他使用
迭代器,它会work@hellzone海报似乎没有删除anything@hellzone我只是在迭代等之后删除块的tick方法中的元素,所以这不是一个问题,对吗?显然是的,否则你不会得到例外,或者只是使用
Iterator
@XtremeBaumer我已经尝试了一个迭代器,但它不起作用,它给出了相同的错误。我现在添加了代码,实际上从LinkedList@XtremeBaumer我不清楚为什么你认为使用迭代器会有区别(我认为自己是一个有经验的java程序员).A for each循环有效地使用了一个迭代器“under the hood”不管怎样。我遗漏了什么吗?当你添加可能的解决方案时,它起作用了!非常感谢!或者只是使用一个
迭代器
@XtremeBaumer我已经尝试了一个迭代器,但它不起作用,它给出了相同的错误。我现在添加了代码,实际上从LinkedList@XtremeBaumer我不清楚你为什么认为使用ITror会有很大的不同(我认为自己是一个有经验的java程序员)。对于每个循环来说,不管怎样,都有效地使用了一个迭代器“在引擎盖下”。我是否缺少了一些东西?当你添加了可能的解决方案时,它就工作了!谢谢!
public void tick(float delta) {
    for (Iterator<Entity> iterator = entities.iterator(); iterator.hasNext();) {
      boolean remove = e.tick(delta);
      if(remove) {
          iterator.remove();
      }
    }
    player.tick(delta);
}
public boolean tick(float delta) {
    if (color == Color.WHITE) {
        if (getSurrounding(-32, -32) != null && getSurrounding(-32, -32).getColor() == Color.BLACK) {
            if (getSurrounding(-32, -32).getStrength() < strength) {
                getSurrounding(-32, -32).setStrength(-50);
            }
        }
    }

    if (!inGame.entities.isEmpty() && strength <= 0) {
        return true;
    }
    return false;
}