zoukankan      html  css  js  c++  java
  • java ArrayList迭代过程中删除

    第一种迭代删除方式:

    第二种迭代删除方式:

    第三种迭代删除:

    第四种迭代删除:

    第五种迭代删除:

     第六种:

    ArrayList中remove()方法的机制,首先看源码:

    真正的删除操作在fastRemove(),首先定义一个新列表的长度newSize,其值为原列表长度减一 (newS-ze = size-1),然后将 索引 i 之后的数组元素全部向前进一位(System.arraycopy(es, i + 1, es, i, newSize - i)),接着最后一个原数组的最后一个元素置为null(es[size = newSize] = null;)。

    所以使用for循环遍历删除的时候,每次循环时都要重新获取ArrayList的长度,并在删除元素之后将索引减1(i--)。

    或者倒序删除。

    迭代器删除:

    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;
    
            // prevent creating a synthetic constructor
            Itr() {}
    
            // 当前迭代指示器是否指向列表末尾
            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 {
                    // 调用fastRemove删除元素
                    ArrayList.this.remove(lastRet);
                    // 迭代指示器指向被删除元素所在的索引位置
                    cursor = lastRet;
                    lastRet = -1;
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
    
            @Override
            public void forEachRemaining(Consumer<? super E> action) {
                Objects.requireNonNull(action);
                final int size = ArrayList.this.size;
                int i = cursor;
                if (i < size) {
                    final Object[] es = elementData;
                    if (i >= es.length)
                        throw new ConcurrentModificationException();
                    for (; i < size && modCount == expectedModCount; i++)
                        action.accept(elementAt(es, i));
                    // update once at end to reduce heap write traffic
                    cursor = i;
                    lastRet = i - 1;
                    checkForComodification();
                }
            }
    
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }

    黄色部分是关键,删除元素后迭代指示器重新指向 “新” 元素,确保每一个元素都能被迭代指示器 “指” 过。

  • 相关阅读:
    Java安全之Filter权限绕过
    Java学习之struts2使用
    Java学习之Hibernate框架使用
    Java学习之Maven使用
    .Net Core3.1中SameSite的使用方法、遇到的问题以及解决办法
    .Net Core 3.1简单搭建微服务
    在VM虚拟机中安装FTP服务
    Hyper-V中的虚拟机(Centos)安装FTP服务
    Docker相关操作
    .Net Core 3.1 服务端配置跨域
  • 原文地址:https://www.cnblogs.com/natian-ws/p/10759616.html
Copyright © 2011-2022 走看看