我知道这样的代码
for ( Object o: collection){
if (condition(i)){
collection.remove(i);
}
}
将抛出 ConcurrentModificationException,我明白为什么:直接修改集合可能会干扰迭代器跟踪其位置的能力,例如,通过引用不再是集合的一部分的元素,或者导致它跳过刚刚添加的一个。对于像上面这样的代码,这是一个合理的问题,但是,我想写一些类似的东西
for (Object o: set){// set is an instance of java.util.LinkedHashSet
if (condition(o)){
set.remove(other(o));
}
}
在集合的顺序中, other(o) 保证与 o 相距“远”。在我的特定实现中,它与 o 的距离永远不会少于 47 个“步骤”。此外,如果 condition(o) 为真,则所讨论的循环将保证在到达 other(o) 所在的位置之前很好地短路。因此,迭代器访问的集合的整个部分与被修改的部分完全解耦。此外,LinkedHashSet 的特殊优势(快速随机访问插入和删除,保证迭代顺序)似乎特别适合这种精确的操作。
我想我的问题是双重的:首先,考虑到上述限制,这样的操作是否仍然危险?我认为可能的唯一方法是 Iterator 值提前预加载并缓存,我认为这会提高许多应用程序的性能,但似乎它也会降低许多其他应用程序的性能,因此是一个来自 java.util 的通用类的奇怪选择。但也许我错了。当谈到缓存之类的事情时,我对效率的直觉常常令人怀疑。其次,假设这种事情至少在理论上是安全的,那么除了完全重新实现LinkedHashSet,或者牺牲效率之外,有没有办法实现这个操作?我可以告诉 Collections 忽略我正在修改 Set 的不同部分的事实吗?照常营业?我目前的解决方法是先将元素添加到中间集合,然后在循环完成后将它们添加到主集合,但这效率低下,因为它必须添加两次值。