iterate over a collection to delete elements

1. Delete elements according to the subscript

1. Test code
		ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
		for(int index = 0 ; index < list.size() ; index++){
			if(Objects.equals("a", list.get(index))){
				list.remove(index);
			}
		}
		System.out.println(String.valueOf(list));


2. Implementation principle

    /**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     *
     * @param index the index of the element to be removed
     * @return the element that was removed from the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    // Remove the element at the specified position in the list.
    // All subsequent elements are shifted left (subscript minus 1).
    public E remove(int index) {
        rangeCheck(index); // Whether it is out of bounds, whether the index is greater than the length of the array

        modCount++; // number of operations
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        // Copy numMoved elements after index+1 to the position of index
        // Overwrite the element at the index position, set the extra position to null, and wait for GC
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }



3. In other cases, this method can be used to
delete a single element, but not in the case of multiple elements,
because after deleting an element, the size of the array and the subscript of the original element will change; it needs to be dealt with accordingly.

		ArrayList<String> list1 = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
		for(int index = 0 ; index < list1.size() ; index++){
			// After deleting index = 0, that is, after element a, the size of the array becomes 3, and the subscript of b becomes 0, so c is deleted again, and finally exits the loop
			list1.remove(index);
		}
		System.out.println(String.valueOf(list1));



Second, foreach

1. Code implementation
		for (String s : list) {
		    if (s.equals("a"))
		        list.remove(s);
		}


Running throws

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForCommodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)


2 .Anomaly Analysis

        // where the exception was thrown
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

    /**
     * An optimized version of AbstractList.Itr
     */
    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() {
            checkForCommodification();// Corresponding 831 lines of code
            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];
        }
}


The chcek was performed during the traversal process from the abnormal information of the positioning

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }


modCount is the actual number of operations on the array, expectedModCount is the expected number of operations
Initialization
        int expectedModCount = modCount;

But at the same time of traversing, the remove operation is performed, resulting in modCount+1, which is inconsistent with expectedModCount

3. Why does the method of deleting elements call Next

java foreach implementation principle In the implementation principle
of foreach, the essence of foreach is the implementation of Iterator

    /**
     * Returns an iterator over the elements in this list in proper sequence.
     *
     * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     *
     * @return an iterator over the elements in this list in proper sequence
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {}


The implementation process of deleting elements
    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }



That is, it can be considered that the Iterator method of the ArrayList is called, and the static class Itr, which is implemented internally, is returned.

In the process of foreach, that is, in the process of the next operation of the Iterator, a check will be performed each time before the next element is obtained.

Throwing is not allowed at the same time. Exceptions for modifying operations

3. Iterator

		Iterator<String> iterator = list.iterator();
		while(iterator.hasNext()){
			if(StringUtils.isNotEmpty(iterator.next())){
				iterator.remove();
			}
		}


Convert a collection to an Iterator Use an Iterator to delete a collection.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326656036&siteId=291194637