ArrayList源码分析

ArrayList内部存储结构就是数组

类结构图

在这里插入图片描述

属性介绍

private static final int DEFAULT_CAPACITY = 10; //默认数组大小

// 空数组,预先创建
private static final Object[] EMPTY_ELEMENTDATA = {};

// 默认空数组,由默认构造方法调用时指定,预先创建,这个数组对象主要是为了扩容时加以区分是否默认情况
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// 真实存储数据的数组
transient Object[] elementData; 

// 数组元数个数
private int size;

构造方法

// 指定容量创建
public ArrayList(int initialCapacity) {
     if (initialCapacity > 0) {
         // 创建容量为initialCapacity的数组
         this.elementData = new Object[initialCapacity];
     } else if (initialCapacity == 0) {
         // initialCapacity为0时,数组指定为EMPTY_ELEMENTDATA
         this.elementData = EMPTY_ELEMENTDATA;
     } else {
         throw new IllegalArgumentException("Illegal Capacity: "+
                                            initialCapacity);
     }
 }

// 默认操作
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 带原始数据的构造方法
public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray(); // 原始数据转成数组
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a; // 原始容器就是ArrayList,那么直接把elementData设置a
        } else {
            // 原始容器不是ArrayList,那么,就把原容器的数据复制成新数组elementData
            elementData = Arrays.copyOf(a, size, Object[].class);
        }
    } else {
        // 原容器是空,那就设置为EMPTY_ELEMENTDATA
        elementData = EMPTY_ELEMENTDATA;
    }
}

add

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 里面会对modCount次数加1
    elementData[size++] = e; // 数组下标后移放入新值
    return true; //返回放入成功
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 确保容量是够的
private void ensureExplicitCapacity(int minCapacity) {
    modCount++; // 结构修改次数加1

    // 要求的容量大小超过了原数组的大小,需要扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity); //扩容
}
// 计算容器的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        // 如果elementData是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那么从DEFAULT_CAPACITY和minCapacity中取最大值
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 直接返回minCapacity
    return minCapacity;
}


扩容

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 新容量为原容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果新容量比要的容量还要小,那么就把当前要的容量设为新容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 新容量比最大值MAX_ARRAY_SIZE大
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity); // 取出所能承受的最大容量
    // 创建newCapacity大小的数组,并把原数组元素复制过去
    elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
    MAX_ARRAY_SIZE;
}

移除元素

每次移除元素都会对数组进行移动,这个性能其实是比较低的,建议ArrayList少做一些增删的操作

// 按下标移除 
public E remove(int index) {
     rangeCheck(index); //检查index的合法性,不能大于size,否则抛出IndexOutOfBoundsException异常

     modCount++;  // 加1
     E oldValue = elementData(index); // 取出index对应的元素

     int numMoved = size - index - 1; // index后面的元素都要移动
     if (numMoved > 0)
         System.arraycopy(elementData, index+1, elementData, index,
                          numMoved);  // 移动元素
     elementData[--size] = null; // 原最后的位置值置null,方便gc

     return oldValue;  // 返回原值
 }
// 按元素对象移除
public boolean remove(Object o) {
    if (o == null) { // 移除的对象本身为null
        for (int index = 0; index < size; index++)
            // 遍历数组,找到第一个为null的元素下标,直接快速移除,并移动元素
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        // 移除的对象本身不为null
        for (int index = 0; index < size; index++)
            // 遍历数组,找到第一个相同的元素下标,直接快速移除,并移动元素
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;  //没找到,返回false
}

private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多栖码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值