ArrayList底层结构和源码分析

发布于:2023-01-16 ⋅ 阅读:(477) ⋅ 点赞:(0)

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

 trainsient Object[] elementData

其中trainsient的意思就是瞬间的,短暂的,不会被序列化

当创建ArrayList对象时,如果使用的是无参构造器,则初始化elementData的容量为0,第一次添加时,扩容elementData为10,如需再次扩容,则扩容为原来的1.5倍

如果使用的是指定elementData容量大小参数的构造器,则初始容器大小为指定大小,如需再次扩容,则变为原来的1.5倍

底层源码分析(以无参构造器为例):

进入ArrayList的无参构造器:

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

再进入DEFAULTCAPACITY_EMPTY_ELEMENTDATA看一下:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

发现DEFAULTCAPACITY_EMPTY_ELEMENTDATA其实就是一个空数组。

list.add()方法调用时的底层源码分析:

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

可以看出: ensureCapacityInternal(size + 1); 先确认一下容量是否够用,

                 elementData[size++] = e;然后在添加元素

进入 ensureCapacityInternal源码:

可以看出,会确定minCapacity,第一次为10

再进入到ensureExplicitCapacity源码:

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

其中modCount++:用来记录当前集合被修改的次数,放置多个线程同时修改这个集合

 if (minCapacity - elementData.length > 0)
            grow(minCapacity);

这个if判断语句的意思就是如果当前容量比应该有的最小容量要小,就说明该扩容了,这个时候执行grow方法才是真正的扩容

进入grow源码:

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

 int oldCapacity = elementData.length;
 int newCapacity = oldCapacity + (oldCapacity >> 1);

oldCapacity >> 1就是除以2的意思,int newCapacity = oldCapacity + (oldCapacity >> 1)就是说newCapacity的大小是oldCapacity的1.5倍

即:第一次newCapacity=10,第二次及以后按照1.5倍扩容,扩容使用的方法是Arrays.copyOf,可以保证原来就有的数据不被覆盖。

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到