当前位置: 首页 > 知识库问答 >
问题:

从列表中移除项时的ConcurrentModificationException

贺亦
2023-03-14

我有一个自定义列表类的应用程序。当尝试使用customer参数执行foreach函数时,会发生以下情况:

XList<Integer> lmod = XList.of(1,2,8, 10, 11, 30, 3, 4);
lmod.forEachWithIndex( (e, i) -> lmod.set(i, e*2));
System.out.println(lmod);
lmod.forEachWithIndex( (e, i) -> { if (i % 2 == 0) lmod.remove(e); } );
System.out.println(lmod);
lmod.forEachWithIndex( (e, i) -> { if (i % 2 == 0) lmod.remove(i); } );
System.out.println(lmod);
public class XList <T> extends ArrayList<T> {
public XList(Collection<T> collection) {
    super(collection);
}

public XList(T... ints) {
    super(Arrays.asList(ints));
}

public static <T> XList<T> of(Set<T> set) {
    return new XList<>(set);
}

public static <T> XList<T> of(T... ints) {
    return new XList<>(ints);
}

public void forEachWithIndex(BiConsumer<? super T, ? super Integer> consumer) {
    Iterator<T> iterator = this.iterator();

    int counter = 0;

    while (iterator.hasNext()) {
        consumer.accept(iterator.next(), counter);
        counter++;
    }
}

错误:

Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
at zad1.XList.forEachWithIndex(XList.java:126)
at zad1.Main.main(Main.java:89)

共有1个答案

陈斌蔚
2023-03-14

ConcurrentModificationException表示:

  1. 在时间点A上,通过调用某个集合.iterator()方法,或者让for(var x:collection){}为您调用该集合来创建迭代器。
  2. 在时间点B,更改集合(而不是通过在a的.remove()方法中创建的迭代器),例如调用removeaddclearremental.
  3. 在时间点C中,您对那个迭代器的观察非常有趣:您调用了它的任何方法,或者您让for循环通过访问它的块的}来完成它。

你需要做的事情绝对不是微不足道的!

当在[0,A]的循环过程中调用.add(“f”)时,也会出现类似的问题。for循环是否应该使用参数[5,F]运行一次lambda?一个悬而未决的问题。

这个问题由你来回答,你应该详细记录下来。无论你做哪一个选择,都是相当困难的!

这是难以置信的复杂。因为假设C的循环最终删除了A。这意味着您的列表将首先调用带有参数[0,A][1,B][2,C]的lambda,然后,下一个迭代将是什么样子?大概唯一合理的答案是[2,D]。为了实现这一点,您需要跟踪所有的事情--列表的循环代码需要知道删除发生了,因此它需要“向下调整”(因为您不能简单地从0循环到“列表大小”,如果这样做了,下一次迭代将是[3,E],即使它仍然在列表中,您也完全跳过了D。

煮点咖啡,钻进去,找块白板,把这个画出来。保留一整天,并意识到代码将会有很多页来处理它。制作大量的测试用例,并详细描述所有这些测试用例中您期望发生的事情。

这比较容易,但效率不高。修复方法很简单:首先制作一份列表副本。然后迭代副本。副本不能更改(您是唯一一个对其有引用的人),所以他们可以对基础列表做任何他们想做的事情:

XList<T> copy = new XList<T>(this);
int counter = 0;

while (iterator.hasNext()) consumer.accept(iterator.next(), counter++);
 类似资料:
  • 我有一个自定义列表类的应用程序。尝试使用customer参数执行foreach函数时,会发生以下情况: 重要!我不能修改主代码 主要内容: XList类: 错误:

  • 问题内容: 在遍历列表时,我想根据条件删除列表中的项。请参见下面的代码。 这给了我一个例外。 如何才能做到这一点? 问题答案: 您需要使用和调用上,而不是使用循环。

  • 这是我一开始的消息来源。 我的名单 如何在不移除0值的情况下从列表中移除None值?

  • 问题内容: 我在Python中有一个列表列表: 我想从中删除重复的元素。如果这是正常列表,而不是我可以使用的列表set。但不幸的是,该列表不可散列,因此无法建立一组列表。只有元组。因此,我可以将所有列表转换为元组,然后使用set并返回列表。但这不是很快。 如何以最有效的方式做到这一点? 上面的结果应为: 我不在乎保留订单。 注意:这个问题很相似,但不是我所需要的。搜索了SO,但没有找到确切的重复项

  • 问题内容: 如果想基于每个嵌套列表的第一个元素评估重复项,谁能提出一个好的解决方案从嵌套列表中删除重复项? 主列表如下所示: 如果已经在第一位置出现了另一个具有相同元素的列表,那么我想删除该列表并得到以下结果: 您可以建议一种算法来实现此目标吗? 问题答案: 您是否关心保留订单/删除了哪些重复项?如果不是,则: 会做的。如果您想保留订单并想保留第一个订单,则:

  • 我有以下代码: 我试图遍历列表中的每个对象,根据条件删除一个项目,并保持循环,直到所有项目都被删除。 当我在intellij中运行这个时,我得到了以下错误: 我搜索了这个问题,找到了这个解决方案。在此处输入链接描述 当我更改代码时,它变成了: 但是,现在我收到以下错误: 我找到了这个错误的答案,但老实说,它并没有为我澄清任何事情。我如何才能从列表中删除该对象?