Collection Alternative – ConcurrentModificationException

我正在迭代一个JRE Collection,它强制执行fail-fast迭代器概念。 问题是如果对象满足条件,我需要删除对象的逻辑伙伴。 从而防止合作伙伴也被处理。 有人可以为此建议更好的收集类型吗?

例。

myCollection for (BusinessObject anObject : myCollection) { if (someConditionIsTrue) { myCollection.remove(anObjectsPartner); // throws ConcurrentModificationException } } 

谢谢。

您想要从列表中删除项目并继续在同一列表上进行迭代。 您是否可以实施两步解决方案,在步骤1中,您收集要在临时收集中删除的项目,并在步骤2中识别它们后删除它们?

这不是系列的错,它就是你使用它的方式。 在迭代中途修改集合会导致此错误(这是一件好事,因为迭代通常无法明确地继续)。

编辑 :重新阅读问题后,这种方法将无效,但我将其留在这里作为一般情况下如何避免此问题的示例。

你想要的是这样的:

 for (Iterator iter = myCollection.iterator; iter.hasNext(); ) { BusinessObject anObject = iter.next(); if (someConditionIsTrue) { iter.remove(); } } 

如果您通过Iterator本身删除对象,它会知道删除并且一切都按预期工作。 请注意,虽然我认为所有标准集合在这方面都能很好地工作,但是迭代器不需要实现remove()方法,所以如果你无法控制myCollection的类(以及返回的迭代器的实现类),你可能需要在那里进行更多的安全检查。

另一种方法(例如,如果您不能保证迭代器支持remove()并且您需要此function)是创建要迭代的集合的副本 ,然后从原始集合中删除元素。

编辑 :您可以使用后一种技术来实现您想要的,但是您最终还是会回到迭代器首先抛出exception的原因: 如果删除了一个没有的元素,迭代应该怎么办?到了吗? 删除(或不删除)当前元素是相对明确定义的,但是你谈到删除当前元素的伙伴 ,我认为它可以在迭代中的随机点。 由于没有明确的方法可以解决这个问题,因此您需要自己提供某种forms的逻辑来应对这种情况。 在这种情况下,我倾向于在迭代期间创建和填充新集合,然后在最后将其分配给myCollection变量。 如果这是不可能的,那么跟踪要删除的伙伴元素并调用myCollection.removeAll将是可行的方法。

一些想法(这取决于集合中两个对象之间的关系到底是什么):

  1. 以对象为键,伙伴为值的Map。
  2. 一个CopyOnWriteArrayList,但是当你击中伙伴时你必须注意
  3. 将副本复制到另一个Collection对象中,并迭代一个,删除另一个。 如果这个原始集合可以是一个集合,那将非常有助于删除。

您可以尝试先找到要删除的所有项目,然后在处理完整个列表后删除它们。 在找到它们时跳过已删除的项目。

 myCollection List deletedObjects = new ArrayList(myCollection.size()); for (BusinessObject anObject : myCollection) { if (!deletedObjects.contains(anObject)) { if (someConditionIsTrue) { deletedObjects.add(anObjectsPartner); } } } myCollection.removeAll(deletedObjects); 

CopyOnWriteArrayList将执行您想要的操作。

为什么不使用所有原始BusinessObject的集合,然后使用一个与它们相关联的单独类(例如Map)(即创建合作伙伴)? 将它们作为复合元素放在它自己的类中,以便在删除Business对象时始终可以删除Partner。 每次需要从Collection中删除BusinessObject时,不要让调用者负责。

IE

 class BusinessObjectCollection implements Collection { Collection objects; Map associations; public void remove(BusinessObject o) { ... // remove from collection and dissasociate... } } 

最好的答案是第二个,使用迭代器。