Java ArrayList.remove不在循环中工作

Java ArrayList.remove不在循环中工作,java,arraylist,Java,Arraylist,我有以下代码- import java.util.ArrayList; public class ArrayListExp{ public static void main (String[] args){ ArrayList<String> name = new ArrayList<String>(); name.add("Chris"); name.add("Lois"); name.add

我有以下代码-

import java.util.ArrayList;

public class ArrayListExp{
    public static void main (String[] args){

        ArrayList<String> name = new ArrayList<String>();

        name.add("Chris");
        name.add("Lois");
        name.add("Meg");
        name.add("Meg");
        name.add("Brain");
        name.add("Peter");
        name.add("Stewie");

        System.out.println(name);

        for ( int i = 0;  i < name.size(); i++){
            String oldName = name.get(i);
            if(oldName.equals("Meg"))
            {
                name.remove(i);
            }
        }

        System.out.println(name);
    }
}

我不明白为什么这不能删除
Meg
,但我只尝试了一个
Meg
,在这种情况下它是有效的。当我在最后添加几个
Meg
时,一个
Meg
不会从
ArrayList
中删除。为什么?

在从0到N迭代ArrayList时,从ArrayList中移除,因此当移除索引N处的第一个Meg时,下一个Meg向下移动到索引N,然后将i增加到N+1。所以第二个梅格没有被移除。尝试以相反的顺序(N到0)迭代:

移除第一个“Meg”时,索引
i=2
。然后它是递增的,但是由于其中一个“Meg”已经被删除,现在
name.get(3)
是“Brain”。所以你没有检查第二个“梅格”

来解决这个问题。删除元素时,可以减小索引:

public class ArrayListExp{
    public static void main (String[] args){

        ArrayList<String> name = new ArrayList<String>();

        name.add("Chris");
        name.add("Lois");
        name.add("Meg");
        name.add("Meg");
        name.add("Brain");
        name.add("Peter");
        name.add("Stewie");

        System.out.println(name);

        for ( int i = 0;  i < name.size(); i++){
            String oldName = name.get(i);
            if(oldName.equals("Meg"))
            {
                name.remove(i);
                i--;
            }
        }

        System.out.println(name);
    }
}
公共类ArrayListXP{
公共静态void main(字符串[]args){
ArrayList name=新的ArrayList();
名称。添加(“克里斯”);
名称。添加(“意向书”);
名称。添加(“Meg”);
名称。添加(“Meg”);
名称。添加(“大脑”);
姓名。添加(“彼得”);
名称。添加(“炖肉”);
System.out.println(名称);
对于(int i=0;i
这是因为当i=2时,如果条件为真,则删除meg,并将所有索引上移。因此,下一步我将指向大脑,而不是梅格

试试这个。(如果条件成立,则将i减少1)

for(int i=0;i
删除循环中不应使用的元素时。它在实现某些逻辑时总是会出现问题。对您的问题使用reverse for loop,并始终尝试对每个问题使用。

您正在迭代第一个
Meg
,当该
Meg
被删除时,数组值会移动一个

[Chris, Lois, Meg, Meg, Brain, Peter, Stewie]
   0     1     2    3     4      5       6
首先,
Meg
被删除,循环增加i,因为它完成了for循环中的所有操作,因此
i
现在将为3,并且数组已被修改:

[Chris, Lois, Meg, Brain, Peter, Stewie]
   0     1     2     3      4      5      
尝试向后迭代

for ( int i = name.size() - 1;  i >= 0; i--){
    String oldName = name.get(i);
    if(oldName.equals("Meg"))
    {
        name.remove(i);
    }
}

您可以使用
name.removeAll(Arrays.asList(“Meg”)删除所有
“Meg”

您的完整代码将是

for ( int i = 0;  i < name.size(); i++){
    String oldName = name.get(i);
    if(oldName.equals("Meg"))
    {
       name.removeAll(Arrays.asList("Meg"));
    }
}
for(int i=0;i
Java8+ 接口现在提供了一个就地修改它的方法,您可以向该方法提供一个谓词,如果该元素应该被删除,该谓词将返回
true

因此,您可以像这样使用lambda:

name.removeIf(name -> name.equals("Meg"));
也可以使用方法引用,使其更加简洁。如果存在
null
元素,则以下代码也将起作用

name.removeIf("Meg"::equals);

如果不想修改旧列表,可以使用和获取通过取消条件应保留的所有项目的
列表

final List<String> filtered = name.stream()
      .filter(name -> !"Meg".equals(name))
      .collect(Collectors.toList());

前Java 8 问题是ArrayList在迭代过程中被修改,这会改变其大小并向前移动后面的元素;如果需要删除连续的元素,则这是一个问题。每次删除一个元素时都需要将索引减少一,因为该索引现在将引用下一个元素

for (int i = 0; i < name.size(); i++) {
    String oldName = name.get(i);
    if (oldName.equals("Meg")) {
        name.remove(i);
        i--;//Important!
    }
}

通常,使用
迭代器
最适合这种操作,因为它支持在通过调用
迭代器#remove
进行迭代时删除元素。这也修改了
列表
。对于更复杂的操作,请考虑使用<代码> ListiTror < /C> > < /P>
final Iterator<String> it = name.iterator();
while(it.hasNext()){
    final String name = it.next();
    if(name.equals("Meg")){
         it.remove();
    }
}
final Iterator it=name.Iterator();
while(it.hasNext()){
最终字符串名称=it.next();
如果(名称等于(“兆欧”)){
it.remove();
}
}

您必须使用迭代器在循环中间移除。这是经常涉及的。在今天晚上之前,我已经看过这个片段至少两次了。如果您仔细查看过去几个小时提交的java文档,您会发现许多有用的评论,这些评论将有助于您的具体案例。
final List<String> filtered = name.stream()
      .filter(name -> !"Meg".equals(name))
      .collect(Collectors.toList());
final ArrayList<String> filtered = name.stream()
       .filter(name -> !"Meg".equals(name))
       .collect(Collectors.toCollection(ArrayList::new));
for (int i = 0; i < name.size(); i++) {
    String oldName = name.get(i);
    if (oldName.equals("Meg")) {
        name.remove(i);
        i--;//Important!
    }
}
for (int i = name.size() - 1; i >= 0; i--) {
    String oldName = name.get(i);
    if (oldName.equals("Meg")) {
        name.remove(i);
    }
}
final Iterator<String> it = name.iterator();
while(it.hasNext()){
    final String name = it.next();
    if(name.equals("Meg")){
         it.remove();
    }
}