Java List remove of

  • 2021-12-09 08:43:00
  • OfStack

Directory 1, Ordinary for Loop through List Delete Specified Element-Error! ! ! 2. When for loops through List to delete elements, let the index adjust synchronously-correct! 3. Traverse List to delete elements in reverse order-correct! 4. foreach traverses List to delete elements-Error! ! ! 5. Iteratively delete List elements-correct! 6. Iterative traversal, deleting elements with list. remove (i) method--Error! ! ! 7. When List deletes elements, pay attention to the difference between Integer type and int type. Summary:

List of Java usually uses list. remove (o)/remove (i) method when deleting elements. When in use, it is easy to touch traps and get unexpected results. Summarize the past experience, record it and share it with you.

First initialize List with the following code:


package com.cicc.am.test;
 
import java.util.ArrayList;
import java.util.List;
 
public class ListTest {
 
 public static void main(String[] args) {
  List<Integer> list=new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(3);
  list.add(3);
  list.add(4);
  System.out.println(list);
 }
}

The output is [1, 2, 3, 3, 4]

1. Ordinary for loops through List to delete specified elements-Error! ! !


for(int i=0;i<list.size();i++){
   if(list.get(i)==3) list.remove(i);
}
System.out.println(list);

Output: [1, 2, 3, 4]

Why is only one element 3 deleted? I thought this code was simple, but I still fell into a trap. If the above code is written like this, Element 3 can't be filtered. As long as there are two adjacent identical elements in list, it can't be filtered completely. After List calls the remove (index) method, Elements at the index location are removed, All the elements after index are moved to the left in turn, that is, the index sequence-1 needs to be used to ensure that all the data can be operated, otherwise the elements with the original index of index+1 cannot be traversed (because the data with the original index of index+1 will become index after the removal operation, and if there is no operation of index-1, it will not be traversed to this element, but will be traversed to the next one of this element).

If so, is it feasible to adjust the index synchronously after deleting elements or traverse the deleted elements in reverse order?

2. When for loops through List to delete elements, let the index adjust synchronously-correct!


for(int i=0;i<list.size();i++){
   if(list.get(i)==3) list.remove(i--);
}
System.out.println(list);

Output: [1, 2, 4]

3. Traverse List to delete elements in reverse order-correct!


for(int i=list.size()-1;i>=0;i--){
 if(list.get(i)==3){
  list.remove(i);
 }
}
System.out.println(list);

Output: [1, 2, 4]

4. foreach Traverses List Delete Elements-Error! ! !


for(Integer i:list){
    if(i==3) list.remove(i);
}
System.out.println(list);

Exception thrown: java. util. ConcurrentModificationException

foreach is actually a shorthand for Iterable, hasNext, next. So start with the List. iterator () source code and trace the iterator () method, which returns the Itr iterator object.


  public Iterator<E> iterator() {
        return new Itr();
    }

The Itr class is defined as follows:


private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
 
        public boolean hasNext() {
            return cursor != size;
        }
 
        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
 
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
 
            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
 
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

Through the code, we find that Itr is a private internal class defined in ArrayList, and checkForComodification method will be called in next and remove methods, which is used to judge modCount! = Whether expectedModCount is equal or not, if not, an ConcurrentModificationException exception is thrown. expectedModCount = modCount is assigned every time the remove method is executed normally, ensuring that the two values are equal, so the problem is basically clear. In the foreach loop,

Execute list. remove (item); The modCount value of the list object is modified, while the expectedModCount value of the iterator of the list object is not modified, thus throwing an ConcurrentModificationException exception.

5. Iteratively delete List elements--Correct!

All collection object types in java implement the Iterator interface, and iteration can be performed during iteration:


Iterator<Integer> it=list.iterator();
 while(it.hasNext()){
  if(it.next()==3){
   it.remove();
  }
        }
System.out.println(list);

Output: [1, 2, 4]

The Iterator. remove () method deletes the current iteration object while preserving the index of the original element. Therefore, iterative deletion of elements is the safest method. It is recommended that you use List process

Use this method when you need to delete elements in.

6. Iterative traversal, deleting elements with list. remove (i) method--Error! ! !


Iterator<Integer> it=list.iterator();
 while(it.hasNext()){
  Integer value=it.next();
   if(value==3){
   list.remove(value);
  }
 }
System.out.println(list);

Throw an exception: java. util. ConcurrentModificationException, as in Method 4 above.

7. When List deletes elements, pay attention to the difference between Integer type and int type.

list of the above Integer, delete element 2 directly, and the code is as follows:


list.remove(2);
System.out.println(list);

Output: [1, 2, 3, 4]

As you can see, when List deletes elements, it deletes them by index by default. If you need to delete the Integer object and call the remove (object) method, you need to pass in the Integer type with the following code:


for(int i=0;i<list.size();i++){
   if(list.get(i)==3) list.remove(i);
}
System.out.println(list);
0

Output: [1, 3, 3, 4]

Summary:

1. When deleting elements by iterating through List with for, it is necessary to pay attention to the problem that the index will shift to the left.

2. When List deletes elements, to avoid traps, it is recommended to use remove mode of iterator iterator.

3. When List deletes an element, it defaults to deleting by index, not by object.


Related articles: