你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

Java源码浅析:ArrayList

2021/12/30 1:00:30

整体架构

是一个数组结构

特点

        删除添加允许放空值,会自动扩容

        Size、isEmpty、set、add等方法时间复杂度O(1)

        非线程安全

        增强for循环,改变列表大小会抛异常

初始化方法

        无参初始化        : ArrayList()

                默认大小时0,第一次添加数据扩容后大小时10

        指定大小初始化 : ArrayList(int initialCapacity)

        执行数据初始化 : ArrayList(Collection<? extends E> c)

扩容机制

        内部判断是否需要扩容,如果需要扩容,扩容后直接赋值

        从第1次扩容起,每次扩容后大小为上一次扩容的1.5倍

        扩容的最大值不会超过Integer的最大值

        扩容的基本原理是通过新建一个符合我们预期容量的新数组,然后把老数组的数据拷贝过去,底层都是通过调用 System.arraycopy 的native方法

关键源码如下:

public boolean add(E e) {
// 确保数组大小是否足够,不够执行扩容, size  为当前数组的大小
ensureCapacityInternal(size + 1); // Increments modCount!!
// 直接赋值,线程不安全的
elementData[size++] = e;
return true;
}

private void ensureCapacityInternal(int minCapacity) {
// 如果初始化数组大小时,有给定初始值,以给定的大小为准,不走 if  逻辑
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 确保容积足够
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
// 记录数组被修改
modCount++;
//  如果我们期望的最小容量大于目前数组的长度,那么就扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 扩容,并把现有数据拷贝到新的数组里面去
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// oldCapacity >> 1  是把 oldCapacity  除以 2  的意思
int newCapacity = oldCapacity + (oldCapacity >> 1);
//  如果扩容后的值 <  我们的期望值,扩容后的值就等于我们的期望值
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//  如果扩容后的值 > jvm  所能分配的数组的最大值,那么就用 Integer  的最大值
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//  通过复制进行扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}

时间复杂度

         O (1) :添加删除只需要通过数组索引

线程不安   

        因为ArrayList自身的elementData(数组列表)、size(大小)、modConut(当前数组被修改的版本次数)变量在多线程环境下进行各种操作时,由于没有加锁,变量类型并非时可见(volatile)的,如果多线程同时操作同个对象,可能存在值被覆盖的风险,所以多线程操作Arraylist建议使用Collections.synchronizedList 生成的ArrayList 内部添加、删除等操作都有加锁,源码如下:

public boolean add(E e) {
synchronized (mutex) {// synchronized  是一种轻量锁, mutex  表示一个当前
SynchronizedList
return c.add(e);
}
}