JDK集合分析(一):ArrayList

本文详细探讨了ArrayList的实现原理,它基于数组实现,允许存储null且线程不安全。ArrayList的add方法未进行线程同步,可能导致并发修改异常。在容量不足时,ArrayList会通过grow方法进行扩容,初始容量不足时按1.5倍增长。文章还提供了ArrayList的构造函数解析,包括无参和带参构造,以及扩容策略的详细步骤。
摘要由CSDN通过智能技术生成

集合

集合主要分为两组(单列集合和双列集合),collection接口有两个子接口,实现的子类均为单列集合。

Map接口的实现的子类均为双列集合

单列集合之ArrayList

ArrayList底层是由数组实现的,允许加入null(多个也允许),线程不安全,下图以ArrayList的add方法为例,可见并没有做线程同步。

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

ArrayList中维护了一个Object类型的数组elementData

无参构造创建ArrayList

创建了一个空的ArrayList

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

add方法

public boolean add(E e) {
        // size是ArrayList类私有变量
        ensureCapacityInternal(size + 1);  // 确认容量够不够
        elementData[size++] = e;
        return true;
    }

判断数组是否为空

private void ensureCapacityInternal(int minCapacity) {
        //比较一下
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

/**
 * @param 对象数组elementData,最小容量minCapacity
 * @return 所需最小容量
 */
 private static int calculateCapacity(Object[] elementData, int minCapacity) {
        // 如果是第一次赋值,即elementData是空数组
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // //给一个默认容量DEFAULT_CAPACITY(10)
            return Math.max(DEFAULT_CAPACITY, minCapacity);  
        }
        return minCapacity;
    }

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;   //记录当前集合被修改的次数,如果有多个线程同时修改会异常

        // overflow-conscious code
        // 如果实际需要的最小容量比能提供的容量要大,就需要扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

扩容函数grow

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // oldCapacity 右移一位即1/2,所以第一次是0
        int newCapacity = oldCapacity + (oldCapacity >> 1);

        //如果扩容后的容量还是小于所需的,就直接按照所需的来设置容量
        //这里其实算是为了修正第一次的0 + 0/2还是0 的bug
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

        // 如果比默认的最大值还大,就调用hugeCapacity
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        // 这里使用copyOf是为了在扩容的时候仍然保留原来的元素
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

有参构造创建ArrayList

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

输入参数是ArrayList的初始大小,因为第一次初始化 this.elementData = new Object[initialCapacity] 就是有大小的数组,因此调用grow扩容的时候第一次就直接按照实际大小的1.5倍来扩容。

 

小tips:

目录

集合

单列集合之ArrayList


IDEA的FILES->Setting->中吧这个选项去掉可以看到完整的集合内部信息,而不是简化后的元素信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值