程序问答   发布时间:2022-05-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了java list.remove 适用于第一个元素,但不适用于其他元素 您如何在迭代期间实际删除项目?后续步骤大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决java list.remove 适用于第一个元素,但不适用于其他元素 您如何在迭代期间实际删除项目?后续步骤?

开发过程中遇到java list.remove 适用于第一个元素,但不适用于其他元素 您如何在迭代期间实际删除项目?后续步骤的问题如何解决?下面主要结合日常开发的经验,给出你关于java list.remove 适用于第一个元素,但不适用于其他元素 您如何在迭代期间实际删除项目?后续步骤的解决方法建议,希望对你解决java list.remove 适用于第一个元素,但不适用于其他元素 您如何在迭代期间实际删除项目?后续步骤有所启发或帮助;

众所周知,不能在 foreach 中使用 List.remove。对我来说,阶段 1 运行正常但阶段 2 不是。有人可以解释一下吗?

第一阶段

List<String> List = new ArrayList<>();
List.add("1");
List.add("2");
for (String item : List) {
    if ("1".equals(item)) {
        List.remove(item);
    }
}
System.out.println(List);

第二阶段

List<String> List = new ArrayList<>();
List.add("1");
List.add("2");
for (String item : List) {
    if ("2".equals(item)) {
        List.remove(item);
    }
}
System.out.println(List);

解决方法

疯了。你在java中发现了一个错误。如此简单的代码 - 令人难以置信。

请参ArrayList的源码。错误是,具体来说,in ArrayList.java on line 962。

通常,数组列表有一个所谓的“mod counter”。任何时候您以任何方式修改数组列表(无论是添加、删除、清除等),modcounter 都会增加 1。

每当您调用 .iterator()for (String item :list) 一开始也执行一次)时,就会创建一个新的迭代器对象(请参阅上面链接中的第 947 行),并且该迭代器对象存储modcount 与创建迭代器时相同。

想法是所有迭代器方法(数量不多;只有 hasNextnextremove)将首先检查后备数组列表(您通过调用其 .iterator() 方法从中获得迭代器的数组列表)与记住的 modcount 不同,如果是,迭代器将立即使用 ConcurrentModificationException 中止。

错误在于hasNext 方法无法做到这一点。我认为这是一个优化,但它导致了一个错误。

因此,发生了这种奇怪的交互:

List<String> list = new ArrayList<String>();

列表的 modcounter = 0。

list.add("1");
list.add("2");
@H_791_2@modcounter 现在是 2。

for (String item : list) {
    if ("1".equals(item)) {
        list.remove(item);
    }
}

这是语法糖。 javac 编译它就好像它读:

Iterator<String> it$1 = list.iterator();
while (it$1.hasNext()) {
    String item = it$1.next();
    // your actual code inside the for loop here:
    if ("1".equals(item)) {
        list.remove(item);
    }
}

所以让我们在此基础上进行讨论:

Iterator<String> it$1 = list.iterator();

一个迭代器对象制作完成;它的 expectedModCount 字段设置为 2,因为这是 list 的当前 modcount。

while (it$1.hasNext()) {

迭代器的位置字段为0,后备列表的大小为2。所以,是的,还有更多的值要返回。 hasNext() 返回 true,进入 while 循环。

String item = it$1.next();
@H_791_2@modcounter 被检查。迭代器的expectedModCount为2,列表的mod计数器为2,所以校验通过,item设置为"1",迭代器的位置字段自增,即现在 1.

if ("1".equals(item)) {
    list.remove(item);
}

该项确实是“1”,因此调用了 list.remove(item)。 list 将其 modcount 更新为 3,将其大小更新为 1,并从其支持数组中删除 "1" 元素。

现在奇怪的事情接踵而至:

while (it$1.hasNext()) {

好吧,hasNext() 不会检查迭代器的 expectedModCount 是否仍然等于列表的 @H_16_7@modCount。如果有,这将失败,但它不会那样做。迭代器的位置字段是1,列表的大小也是1,所以hasNext()返回false,while循环退出。就是这样:我们在没有遇到 ConcurrentModificationException 的情况下就退出了循环。

相反,在第二个代码段中,您在 next() 上调用 it$1 两次,然后删除该元素。此时调用hasNext(),然后迭代器的position字段为2,列表大小为1,具体检查(ArrayList的第962行)检查是否listSize != iteratorPosition。因此,它不是,hasNext 返回 true(有点奇怪)。因此,while 循环第三次进入主体,运行 String item = it$1.next(),而 next() 方法确实进行 modCount 检查。 expectedModCount 为 2,列表的 @H_16_7@modCount 为 3,因此 CoModEx 被抛出。

要重现这一点,您需要像这样删除数组列表中的倒数第二个元素。在您的 2 个元素的示例列表中,这将是第一个元素。

您如何在迭代期间实际删除项目?

正确的策略是使用迭代器的 remove 方法。你不能在 for(:) 循环中访问迭代器,所以写:

Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String item = it.next();
    if ("2".equals(item)) {
        it.remove(); // this is how to do it!
    }
}

remove() 在迭代器上是唯一的:假设 modcount 检查通过,它会增加迭代器的预期 modcount 以及支持列表的 mod 计数:这是在没有迭代器的情况下在迭代期间修改列表的唯一方法失败了(好吧,那个,还有你发现的这个错误)。

后续步骤

我会针对这个问题在 openjdk 提交一个错误。

大佬总结

以上是大佬教程为你收集整理的java list.remove 适用于第一个元素,但不适用于其他元素 您如何在迭代期间实际删除项目?后续步骤全部内容,希望文章能够帮你解决java list.remove 适用于第一个元素,但不适用于其他元素 您如何在迭代期间实际删除项目?后续步骤所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:list.remove