ArrayList源码分析

ArrayList源码分析

默认大小

// 根据传入的初始化大小创建对应的数组大小
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        // 根据传入的值、创建对应的Object数组
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        // 为0则赋值一个空的Object数组
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        // 传入的值错误
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

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

如果不传入初始化大小的话、则默认的大小为一个空的Object数组

扩容机制

// 直接往数组尾部添加元素
public boolean add(E e) {
    // modCount线程安全相关检查、以及扩容机制的具体操作
    ensureCapacityInternal(size + 1); 
    // 往数组尾部添加、即数组长度、添加完后在自增
    elementData[size++] = e;
    return true;
}

// 根据索引往数组插入元素
public void add(int index, E element) {
    // 索引检查
    rangeCheckForAdd(index);

    // modCount线程安全相关检查、以及扩容机制的具体操作
    ensureCapacityInternal(size + 1);
    
    // 数组拷贝、在要插入的索引位置把数组向右移动一位、然后在给索引位置赋值
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    // 数组长度自增
    size++;
}

// 确保集合容量、传入现在需要的数组长度大小
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

// 里面调用了扩容操作、传入的是当前数组需要的最小长度
private void ensureExplicitCapacity(int minCapacity) {
    // 线程安全相关
    modCount++;
	
   	// 当前数组需要的长度大于当前数组长度时、执行扩容
    if (minCapacity - elementData.length > 0)
        // 执行数组扩容操作、根据传入的长度扩容几倍的数组大小
        grow(minCapacity);
}

// 计算一下扩容的大小、传入当前数组和当前需要的长度
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    // 如果数组是默认的空数组、则返回默认为10的长度、不是的话返回当前需要的长度
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

private void grow(int minCapacity) {
    // 当前数组长度
    int oldCapacity = elementData.length;
    // 新的数组长度 = 需要的数组长度 + 需要的数组长度 / 2
    int newCapacity = oldCapacity + (oldCapacity >> 1);

    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 扩容数组、拷贝一个新的数组返回、根据newCapacity长度
    elementData = Arrays.copyOf(elementData, newCapacity);
}

索引检查

// 索引检查
private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
posted @   鐡道  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示