我有以下代码:
class Action {
public void step(Game game) {
//if some condition met,
// then remove self from action stack
game.actionStack.remove(this);
}
class Game (
public ArrayList<Action> actionStack;
public Game() {
actionStack = new Arraylist<Action>();
actionStack.add(new Action());
while (true) {
for (Action action : this.actionStack) {
action.step(this);
}
}
}
}
发生game.actionStack.remove(this);
时会抛出异常。有没有办法从我想要的Action
类中安全地删除元素?
答案 0 :(得分:4)
我猜你得到了一个ConcurrentModificationException,因为你在迭代时调用了list remove方法。你不能这样做。
一个简单的解决方法是在迭代时处理数组的副本:
for (Action action : new ArrayList<>(this.actionStack)) {
action.step(this);
}
稍微高效的修复方法是使用显式迭代器并调用其remove方法。或许step()
返回一个布尔值,表示是否要保留在列表中以进行下一步:
for (Iterator<Action> it = this.actionStack.iterator(); it.hasNext();) {
Action action = it.next();
if (!action.step(this)) {
it.remove();
}
}
答案 1 :(得分:1)
来自:the java tutorial我们得到以下内容:
迭代器
...
请注意
Iterator.remove
是在迭代期间修改集合的唯一安全方法;如果在迭代进行过程中以任何其他方式修改基础集合,则行为未指定。在需要时使用
Iterator
代替for-each
构造:
- 删除当前元素。
for-each
构造隐藏了迭代器,因此您无法调用remove
。因此,for-each
构造不可用于过滤。- 并行迭代多个集合。
以下方法向您展示如何使用
Iterator
过滤任意Collection
- 也就是说,遍历删除特定元素的集合。
static void filter(Collection<?> c) {
for (Iterator<?> it = c.iterator(); it.hasNext(); )
if (!cond(it.next()))
it.remove();
}
这段简单的代码是多态的,这意味着无论实现如何,它都适用于任何
Collection
。此示例演示了使用Java Collections Framework编写多态算法是多么容易。
答案 2 :(得分:0)
注意:我认为,您为班级实施了equals
和hashCode
方法
您需要使用迭代器来删除,如下所示;
class Game (
public ArrayList<Action> actionStack;
public Game() {
actionStack = new Arraylist<Action>();
actionStack.add(new Action());
while (true) {
for (Iterator<Action> it = this.actionStack.iterator(); it.hasNext(); ) {
it.remove();
}
}
}
}
编辑:步骤功能是做简单的删除工作。我将其移至Game
构造函数
答案 3 :(得分:0)
我怀疑你得到了一个并发修改例外。我建议你这样做
class Action {
public void step(Game game) {
//if some condition met,
// then remove self from action stack
List<Action> tmpActionList = new List<Action>();
tmpActionList = game.actionStack
tmpActionList.remove(this);
game.actionStack = tmpActionList;
}
}
让我知道它是否有效。