ArrayList.remove is not working in a loop

后端 未结 7 1607
南旧
南旧 2020-11-29 09:46

I have following code-

import java.util.ArrayList;

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

        ArrayList          


        
7条回答
  •  春和景丽
    2020-11-29 09:54

    Java 8+

    The Collection interface now provides a removeIf method that modifies it in place, to which you provide a predicate that returns true if the element should be removed.

    You can thus use a lambda like so:

    name.removeIf(name -> name.equals("Meg"));
    

    A method reference can be used as well to be more concise. The following code will also work if there are null elements.

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

    If you do not want to modify the old list, you can use Stream and filter to get a List of all the items that should be retained by negating the condition.

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

    If you specifically need an ArrayList, use Collectors.toCollection with a constructor reference instead.

    final ArrayList filtered = name.stream()
           .filter(name -> !"Meg".equals(name))
           .collect(Collectors.toCollection(ArrayList::new));
    

    Pre Java 8

    The issue is that the ArrayList is being modified while being iterated over, which changes its size and shifts later elements forward; this is a problem if there are consecutive elements that need to be removed. You need to decrease the index by one each time you remove an element since that index will now refer to the next element.

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

    Looping backwards will also fix this problem, as elements will never be shifted to a position that have yet to be checked.
    for (int i = name.size() - 1; i >= 0; i--) {
        String oldName = name.get(i);
        if (oldName.equals("Meg")) {
            name.remove(i);
        }
    }
    

    Generally, using an Iterator is the most appropriate for this sort of operation, as it supports removing elements while iterating through calling Iterator#remove. This also modifies the List in place. For more complex operations, consider using a ListIterator.

    final Iterator it = name.iterator();
    while(it.hasNext()){
        final String name = it.next();
        if(name.equals("Meg")){
             it.remove();
        }
    }
    

提交回复
热议问题