我有一个在arraylist中的对象,称为PowerUp
。我希望这些是可点击的,当它们被点击时,它们将从屏幕上移除,并最终从arraylist中取出。我已将处理程序插入到类HealthPack
中,后者又扩展了PowerUp
。我正在尝试访问点击的某个HealthPack
并将其从该列表中删除。我一直无法正常工作,或ConcurrentModificationException
。这是我正在尝试使用的代码:
for (int i = 0; i < ((SurvivalMode) m).getPowerUps().size(); i++) {
PowerUp p = ((SurvivalMode) m).getPowerUps().get(i);
if (p.equals(hp)) { // HealthPack hp = this;
((SurvivalMode) m).getPowerUps().remove(p);
addPoints();
}
}
当我在列表同时添加ConcurrentModificationException
并且另一个正在迭代它时,当我点击HealthPack
时,此当前代码实际上会抛出ConcurrentModificationException
。我曾尝试同步混乱列表的方法,但它没有帮助。
如果一个方法试图从列表中删除一个元素而另一个方法正在遍历列表,或者一个是从列表中添加或删除元素,那么如何让我的程序抛出if (powerups.size() >= 15 || isPaused()) return;
int gen = random.nextInt(10);
if (gen == 0) {
powerups.add(new HealthPack(this));
addMouseListener(powerups.get(powerups.size() - 1).getMouseListener());
}
}
?
修改
以下是一些实际修改项目的arraylist的其他代码:
ConcurrentModificationException
和一些实际遍历该列表的代码(抛出for (PowerUp p : powerups) p.update();
):
PowerUp
当前方法:
这是我尝试在点击时从列表中删除的当前方法,但它仍然不能很好地工作,因为它根本不删除任何内容或者它将删除错误的方法,有时甚至调用列表中所有其他Iterator<PowerUp> iter = ((SurvivalMode) m).getPowerUps().iterator();
while (iter.hasNext()) {
PowerUp p = (HealthPack) iter.next();
if (p.equals(hp)) {
((SurvivalMode) m).getPowerUps().remove(p);
}
CellDefender.getSounds().play(SoundType.HEALTH_PACK);
break;
}
的方法:
CopyOnWriteArrayList<PowerUp> cpowerups = new CopyOnWriteArrayList<PowerUp>();
for (int i = 0; i < powerups.size(); i++) {
cpowerups.add(powerups.get(i));
}
for (PowerUp p : cpowerups) p.update();
更新2:
我最近做的是实际上在另一个点复制数组列表,它部分有助于减少错误(在我的更新方法中):
{{1}}
我想问一件事,是否有办法检测列表当前是否正在被修改,以及是否正在修改列表以突破循环?
答案 0 :(得分:0)
您必须使用Iterator
for循环删除ArrayList
中的元素。
Iterator<PowerUp> iter = ((SurvivalMode) m).getPowerUps().iterator();
while(iter.hasNext()) {
PowerUp p = iter.next();
// your conditions to remove element here
iter.remove();
}
答案 1 :(得分:0)
由于我不知道你的整个代码,我必须做出一些假设。
我的第一个假设是,update
类的PowerUp
方法以某种方式调用有问题的代码片段。
正如[1]中所述,每个循环的a使用Iterator
对象来迭代ArrayList
的元素。
Iterator
返回的ArrayList
个对象故障快速。
也就是说,如果在创建这样的ConcurrentModificationException
对象之后以任何方式修改ArrayList
,则它们的方法会抛出Iterator
,除非通过对象本身。 (参见[2])
如果我的假设是正确的,那么您的代码for (PowerUp p : powerups) p.update();
会创建一个Iterator
对象并修改其他给定代码片段中的ArrayList
。
这就是为什么你遇到与Alex提出的代码相同的异常的原因。
问题的解决方案是,只要您对CopyOnWriteArrayList
(Collection
,ArrayList
等进行迭代,就会使用LinkedList
。它会创建一个浅层副本集合并迭代副本的元素,以便您可以修改原始集合而不会出现ConcurrentModificationException
。
这意味着,您必须将for (PowerUp p : powerups) p.update();
替换为for (PowerUp p : CopyOnWriteArrayList(powerups) p.update();
并使用
Iterator<PowerUp> iter = ((SurvivalMode) m).getPowerUps().iterator();
while(iter.hasNext()) {
PowerUp p = iter.next();
// your conditions to remove element here
iter.remove();
}
由Alex提出。