ArrayList扩容源码分析

2022/2/23 11:52:24

本文主要是介绍ArrayList扩容源码分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

ArrayList扩容源码分析

结论

  1. 实际是维护了一个Object类型的数组(transient Object[] elementData)

    transient表示瞬时,表示该属性不会被序列化

  2. 创建ArrayList时,调用无参构造

    初始elementData容量为0第一次添加时,扩容至10

    如果需要再次扩容时,则扩容为1.5倍

  3. 创建ArrayList时,调用指定大小的构造器时

    初始elementData容量为指定大小

    如果需要再次扩容时,则扩容为1.5倍


分析源码:

无参构造时的扩容

无参构造

public ArrayList() {
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
    // 创建了一个空的elementData
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

说明第一次初始化时容量为0


添加方法add()

public boolean add(E e) {
    // 扩容
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // 再添加
    elementData[size++] = e;
	// 100%返回true
    return true;
}

确认容量ensureCapacityInternal()

protected transient int modCount = 0;
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// ensureCapacityInternal()
// 此时参数为size + 1
private void ensureCapacityInternal(int minCapacity) {
    	// 调用函数
    	// ensureExplicitCapacity()
    	// 将calculateCapacity(elementData, minCapacity)的返回值作为参数
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }


// calculateCapacity()
// 用于确定一个minCapacity
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    	// 如果elementData等于空
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 返回一个DEFAULT_CAPACITY 和 minCapacity比较出的最大值
            // private static final int DEFAULT_CAPACITY = 10;
            // 也就是说minCapacity<10时,返回的是10
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    	// minCapacity>10时,返回的是minCapacity
        return minCapacity;
    }


// ensureExplicitCapacity()
// 此时minCapacity为calculateCapacity()返回值
// size+1<10时,返回的是10
// size+1>10时,返回的是size+1
private void ensureExplicitCapacity(int minCapacity) {
    	// 记录当前集合被修改的次数
    	// 多线程修改时会抛出异常
        modCount++;

        // overflow-conscious code
    	// 当minCapacity大于当前elementData长度时
        if (minCapacity - elementData.length > 0)
            // 扩容
            // 调用grow()
            // 参数为minCapacity
            grow(minCapacity);
    }

// grow()
private void grow(int minCapacity) {
        // overflow-conscious code
    	// elementData数组长度
    	// 第一次进来是0
        int oldCapacity = elementData.length;
    	// 用elementData数组长度+elementData数组长度右移一位(正数是相当于除以2)赋给新容器
    	// 也就是原来elementData数组长度的1.5倍
    	// 第一次是0
    	// 第一次没有真正的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
    	
    	// 如果minCapacity比newCapacity大
    	// 第一次0 - 10 < 0
        if (newCapacity - minCapacity < 0)
            // 那就将minCapacity赋给newCapacity
            // 第一次newCapacity为10
            newCapacity = minCapacity;
    
    	// 如果newCapacity 比 MAX_ARRAY_SIZE大
    	// @Native public static final int   MAX_VALUE = 0x7fffffff;
    	// private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    	// MAX_ARRAY_SIZE 是 0x7fffffff - 8
    	// 2的31次方-1-8
    
    	// newCapacity比最大容量还大的话
    	// 一般不会
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            // 比最大容量还大的话调用hugeCapacity()
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
    	// 正常情况调用Arrays.copyOf()
    	// 通过拷贝达到给elementData赋值newCapacity长度的效果
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
	// grow()结束到:
	// ensureExplicitCapacity()结束到:
	// ensureCapacityInternal()结束到add():
	
	public boolean add(E e) {
    	// 扩容
    	ensureCapacityInternal(size + 1);  // Increments modCount!!
    	// 赋值
    	elementData[size++] = e;
		// 100%返回true
    	return true;
	}
	
	// add()结束

指定大小的构造器时的扩容

有参构造

public ArrayList(int initialCapacity) {
    // 如果参数 > 0
    if (initialCapacity > 0) {
        // 创建一个长度为参数的Object[]赋给elementData
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        // 如果参数为0
        // private static final Object[] EMPTY_ELEMENTDATA = {};
        // 赋值空数组
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        // 负数抛一个异常
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
    }
}

add()

public boolean add(E e) {
    // 扩容
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // 再添加
    elementData[size++] = e;
	// 100%返回true
    return true;
}

不同在扩容的判断

private void ensureCapacityInternal(int minCapacity) {
    	// 调用函数
    	// ensureExplicitCapacity()
    	// 将calculateCapacity(elementData, minCapacity)的返回值作为参数
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }


// calculateCapacity()
// 用于确定一个minCapacity
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    	// 如果elementData等于空
    	// 此时不为空
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 不走这一步
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    	// 返回的是size+1
        return minCapacity;
    }


// ensureExplicitCapacity()
// 此时minCapacity为calculateCapacity()返回值
// 返回的是size+1
private void ensureExplicitCapacity(int minCapacity) {
    	// 记录当前集合被修改的次数
    	// 多线程修改时会抛出异常
        modCount++;

        // overflow-conscious code
    	// 当minCapacity大于当前elementData长度时
    	// 初始够用就不扩,不够用就进
        if (minCapacity - elementData.length > 0)
            // 扩容
            // 调用grow()
            // 参数为minCapacity
            grow(minCapacity);
    }

// grow()
private void grow(int minCapacity) {
    	// elementData数组长度
        int oldCapacity = elementData.length;
    	// 用elementData数组长度+elementData数组长度右移一位(正数是相当于除以2)赋给新容器
    	// 也就是原来elementData数组长度的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
    	
    	// 如果minCapacity比newCapacity大
        if (newCapacity - minCapacity < 0)
            // 那就将minCapacity赋给newCapacity
            newCapacity = minCapacity;
    
    	// 如果newCapacity 比 MAX_ARRAY_SIZE大
    	// newCapacity比最大容量还大的话
    	// 一般不会
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            // 比最大容量还大的话调用hugeCapacity()
            newCapacity = hugeCapacity(minCapacity);
       
    	// 正常情况调用Arrays.copyOf()
    	// 通过拷贝达到给elementData赋值newCapacity长度的效果
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
	// grow()结束到:
	// ensureExplicitCapacity()结束到:
	// ensureCapacityInternal()结束到add():
	
	public boolean add(E e) {
    	// 扩容
    	ensureCapacityInternal(size + 1);  // Increments modCount!!
    	// 赋值
    	elementData[size++] = e;
		// 100%返回true
    	return true;
	}
	
	// add()结束


这篇关于ArrayList扩容源码分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程