Java—在使用for索引循环迭代列表时删除列表中的元素

Java—在使用for索引循环迭代列表时删除列表中的元素,java,Java,我知道不建议在迭代时从列表中删除元素。 最好使用iterator.remove()、java streams或将remove复制到外部列表 但这个简单的代码只起作用: static List<Integer> list = new ArrayList<Integer>(); ... private static void removeForI() { for (int i = 0; i < 10; i++) { if (i == 3)

我知道不建议在迭代时从列表中删除元素。
最好使用iterator.remove()、java streams或将remove复制到外部列表

但这个简单的代码只起作用:

 static List<Integer> list = new ArrayList<Integer>();
 ...
 private static void removeForI() {
    for (int i = 0; i < 10; i++) {
        if (i == 3) {
            list.remove(i);
            continue;
        }
        System.out.println(i);
    }
 }
static List=new ArrayList();
...
私有静态void removeForI(){
对于(int i=0;i<10;i++){
如果(i==3){
列表。删除(i);
继续;
}
系统输出打印LN(i);
}
}

使用它安全吗?

您需要考虑一下
list.remove(index)
的工作原理。 调用
remove(idx)
时,将删除
idx
索引处的元素,并将接下来的所有元素移到左侧。 假设你有一个包含2,3,3,4,5的列表。现在,您希望从此列表中删除所有3。但是如果您使用当前的方法,它将只删除第一次出现的3。因为在移除位置1的第1次出现的3之后,你的内容会向左移动,就像这样2,3,4,5。但是现在for循环将当前索引增加到2,其中包含4而不是3。 这就是为什么不建议在迭代时删除项,因为每次删除后项的索引都会更改


编辑:如果您在循环中断条件中使用常量值,如上例
i中所示,则需要考虑
list.remove(index)
的工作原理。 调用
remove(idx)
时,将删除
idx
索引处的元素,并将接下来的所有元素移到左侧。 假设你有一个包含2,3,3,4,5的列表。现在,您希望从此列表中删除所有3。但是如果您使用当前的方法,它将只删除第一次出现的3。因为在移除位置1的第1次出现的3之后,你的内容会向左移动,就像这样2,3,4,5。但是现在for循环将当前索引增加到2,其中包含4而不是3。 这就是为什么不建议在迭代时删除项,因为每次删除后项的索引都会更改


编辑:如果您在循环中断条件下使用常量值,如上例
i中所示,即使它在人们指出的条件下工作,我也只会暂时使用它,并将其更改为:

private static void removeForI() {
    list.remove(3);
    list.foreach(System.out::println);
}

无需检查i==3,只需在for循环之前删除它。

即使它在人们指出的条件下工作,我也只会暂时使用它,并将其更改为:

private static void removeForI() {
    list.remove(3);
    list.foreach(System.out::println);
}

无需检查i==3,只需在for循环之前删除它。

该循环稍后将具有不同的条件,否则您只需按照JoschJava所述操作即可

但是,如果您确实希望遍历所有元素,并在循环过程中删除一个特定的元素,那么您可能需要在循环结束后向后移动索引。如果是这样的话,我会在你的附条件正文末尾加上:


i-=1

看起来该循环稍后将有一个不同的条件,否则您可以简单地按照JoschJava所述执行

但是,如果您确实希望遍历所有元素,并在循环过程中删除一个特定的元素,那么您可能需要在循环结束后向后移动索引。如果是这样的话,我会在你的附条件正文末尾加上:


i-=1

这根本不安全。当您知道在迭代过程中可能会调整列表时,请将列表对象转换为迭代器对象,然后使用其方法:hasNext、next、remove…

这根本不安全。当您知道在迭代过程中可能会调整列表时,请将您的列表对象转换为迭代器对象,然后使用其方法:hasNext,next,remove…

是,假设列表至少有4个元素要开始。是的,如果您不使用迭代器,就可以了。只需确保您的索引在删除后位于您希望的位置。它将跳过从索引4开始的元素。@LouisWasserman这是一个技巧性问题。它只是打印
i
,而不是索引
i
处的元素。结果是第四个元素从列表中删除,代码打印
012456789
,跳过数字
3
,但不跳过任何元素。好吧,如果您知道自己在做什么,您肯定可以像您所展示的那样做。这只是因为它常常是潜在bug的来源,因为人们往往忘记了,如果他们这样做,他们需要小心。这就是为什么
迭代器
实现在对其进行迭代并修改基础集合时会抛出一个
ConcurrentModificationException
。是的,假设列表至少有4个元素要开始。是的,如果不使用迭代器就可以了。只需确保您的索引在删除后位于您希望的位置。它将跳过从索引4开始的元素。@LouisWasserman这是一个技巧性问题。它只是打印
i
,而不是索引
i
处的元素。结果是第四个元素从列表中删除,代码打印
012456789
,跳过数字
3
,但不跳过任何元素。好吧,如果您知道自己在做什么,您肯定可以像您所展示的那样做。这只是因为它常常是潜在bug的来源,因为人们往往忘记了,如果他们这样做,他们需要小心。这就是为什么
迭代器
实现在对其进行迭代并修改基础集合时会抛出一个
ConcurrentModificationException
。可能条件并不是只删除第三个元素那么简单。否则,在示例中,当删除第三个元素时,没有理由保持循环。。。有可能只是
中断而不是
继续