gpt4 book ai didi

Java 同级删除抛出 ConcurrentModificationException

转载 作者:行者123 更新时间:2023-12-01 14:32:49 25 4
gpt4 key购买 nike

我遇到以下问题:

给定:

public class A{
Collection<B> elements = new ArrayList<B>();
}

public class B{
Collection<B> linkedElements = new ArrayList<B>();
}

linkedElements 的所有元素也属于元素。我希望每次从元素集合中删除一个元素时,它的链接元素也会从该集合中删除。我尝试将观察者附加到 Iterator.remove 操作,并在那里触发从元素列表中删除 linkedElements,但由于逻辑本身,我总是遇到 ConcurrentModificationException。

更新:这是导致错误的代码:

public class A{
Collection<B> elements = new ArrayList<B>(){
public Iterator<B> iterator() {
return new ProxyIterator(super.iterator());
};

private class ProxyIterator implements Iterator{

Iterator it;

Object lastObject;

public ProxyIterator(Iterator proxied){
it = proxied;
}

@Override
public boolean hasNext() {
return it.hasNext();
}

@Override
public Object next() {
return lastObject = it.next();
}

@Override
public void remove() {
it.remove()
for (B linkedElement : ((B)lastObject).getlinkedElements()) {
A.this.getElements().remove(linkedElement);
}
}

}
}

使用此代码,只需调用 A.getElements().clear() 就会引发 ConcurrentModificationException...并且可以,因为我要删除所有从元素列表中链接元素,同时删除一个元素。这就是为什么我需要另一种方法。

最佳答案

这是因为您在迭代数组时修改了数组。来自 ArrayList 的 javadoc:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

因此,一旦您在remove方法中执行了A.this.getElements().remove(linkedElement);,您现在就通过迭代器以外的方式对列表进行了结构修改it 的“remove”方法,这意味着迭代器将抛出 CME。

处理这个问题可能会很棘手。我可以立即想到一些选择,但所有这些都有复杂性:

  • 切换到CopyOnWriteArrayList,因为它的迭代器是故障安全的。缺点是您的迭代器可能仍会显示之前删除的项目。 (另一方面,无论如何,您都必须处理这种风险,因为您也可能已经迭代了要删除的任何子项。)如果这对您有用,那么这几乎肯定是最简单和最可靠的选项。
  • remove 中的for 循环之后,将it 替换为您手动前进到正确位置的新迭代器。如果您的列表允许重复的项目,则很难做到。
  • 重新实现ArrayList.Iterator;在您的 remove 方法中,您可以跟踪您所做的更改并相应地更新您的迭代器。

最后,作为最后一个问题/警告 - 你希望这种遍历是递归的吗?现在,如果元素 Foo 链接到 Bar,Bar 链接到 Baz,从迭代器中删除 Foo 将导致 Bar 被删除,但没有任何内容可以删除 Baz。 (而如果您先删除 Bar,那么 Baz 也会被删除。)一般来说,如果您想修改 Collection 的删除行为,最好执行 List.remove 而不是 Iterator.remove

关于Java 同级删除抛出 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16722162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com