ArrayList源码分析

123 阅读1分钟

容量

 //初始化 ArrayList的容量为10
 private static final int DEFAULT_CAPACITY = 10;`

添加

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

ensureCapacityInternal方法是这样的

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    private void ensureExplicitCapacity(int minCapacity) {
    //这个modCount在集合类中经常会见到,其意思很简单,就是记录修改次数,一般用上这个参数的都是线程不安全的类,例如 hashmap ArrayList linklist 等
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        // oldCapacity为10
        int oldCapacity = elementData.length;
        //连续两个>>表示右移,高位补符号位 右移位表示除2,也就是10+5=15
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 在这里可以看到,数组的扩容是通过将一个原来数组中的数据复制到一个更大容量的数组来进行扩容的
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

上一段代码牵扯到了elelmentdata

    transient Object[] elementData; 

这个elementDate很有意思,它是数组的缓冲区,缓冲区的大小就是默认的10,不过是只有当添加元素的时候,这个容量才会变回10,否则容量还是0

    //int类型默认最大的是2的32次方
    @Native public static final int   MAX_VALUE = 0x7fffffff;
    //数据最大长度就是2的32次方-8
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

上面这段代码逻辑十分简单,就是minCapacity的容量小于0,就抛出错误,否则就看minCapacity和max_array_size 大小比较,minCapacity大的话,就返回Integer.MAX_VALUE,否则返回MAX_ARRAY_SIZE

线程不安全

推荐看why的文章
mp.weixin.qq.com/s/MNeD5Idjq…

删除

遍历的集合直接使用remove删除会出现问题