美文网首页
ArrayList源码分析

ArrayList源码分析

作者: 四喜汤圆 | 来源:发表于2018-09-02 18:44 被阅读0次
    image.png

    1. 增

    boolean add(E e)源码执行流程图

    boolean add(E e)

    boolean addAll(int index,Collection<? extends E> c )源码执行流程图

    boolean addAll(int index,Collection<? extends E> c )

    2. 删

    boolean removeAll(Collection<? extends E> c)批量删除

    public boolean removeAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, false);
    }
    

    removeAll()方法实际上调用的是batchRemove()方法

    /**
         * ArrayList中的元素实际上保存在一个Object[]中,
         * 从该数组中删除object[] 和Collection<?> C的公共元素
         * 
         * @param c
         * @param complement
         * @return
         */
        private boolean batchRemove(Collection<?> c, boolean complement) {
            final Object[] elementData = this.elementData;
            int w = 0, r = 0;
            boolean modified = false;
            try {
    
                for (; r < size; r++) {
                    // 遍历elementData中的元素
                    if (c.contains(elementData[r]) == complement) {
                        // c中不包含当前元素,则该元素需要保留在elementData中
                        elementData[w++] = elementData[r];
                    }
                }
            } finally {
                /*
                 * 如果上述遍历过程发生异常的话(出现异常会导致r!=size),
                 * 则将异常处到size-1位置的元素全部保留在elementData中,不做删除
                 */
                if (r != size) {
                    System.arraycopy(elementData, r, elementData, w, size - r);
                    w += size - r;// 修改 w数量
                }
                // 把[w,size-1]索引处的元素设置为null,防止内存泄漏
                if (w != size) {
                    for (int i = w; i < size; i++) {
                        elementData[i] = null;
                        modCount += size - w;// 修改modCount
                        size = w;// 修改size
                        modified = true;
                    }
                }
    
            }
            return complement;
        }
    

    代码,高效寻找两个集合中公共元素

    3. 改

    4. 查

    查实际上都是遍历Object[] 数组

    public int indexOf(Object o) {
            if (o == null) {
                for (int i = 0; i < size; i++)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = 0; i < size; i++)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
    
    public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    
    public int lastIndexOf(Object o) {
            if (o == null) {
                for (int i = size-1; i >= 0; i--)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = size-1; i >= 0; i--)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
    

    5. 排序

    public void sort(Comparator<? super E> c) {
            final int expectedModCount = modCount;
            Arrays.sort((E[]) elementData, 0, size, c);
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
    

    相关知识点

    1. Arrays.sort() // 对传入的数组进行排序
    2. Arrays.copyOf()
    // 创建一个长度为newLength的新数组,
    //   若newLength>原数组长度:将多出来元素控件用false补齐
    //   若newLength>原数组长度:将原数组多出来的元素截断
    static boolean[] copyOf(boolean[] original, int newLength)
    
    // 把原数组中[from,to]范围内的数拷贝到一个新数组中,返回新数组
    static copyOfRange (boolean[] original, int from, int to)
    

    参考文献

    面试必备:ArrayList源码解析(JDK8)

    相关文章

      网友评论

          本文标题:ArrayList源码分析

          本文链接:https://www.haomeiwen.com/subject/dkrpwftx.html