ArrayList源码解析(1.8)

 


概述

ArrayList是一个集合,实现了List接口,底层是基于数组实现。
ArrayList容器中的数据都是有序的,并且可以存储null值。
ArrayList进行遍历时,可以通过iterator进行遍历,也可以通过下标获取元素。
ArrayList是非线程安全的。

数据结构

ArrayList底层是基于Object数组进行实现。

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer. Any
 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 * will be expanded to DEFAULT_CAPACITY when the first element is added.
 */
transient Object[] elementData; // non-private to simplify nested class access

成员变量

/**
 * 数组默认初始长度
 */
private static final int DEFAULT_CAPACITY = 10;

/**
 * 主实例数组,主要用于创建数组长度为0时的默认值
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * 空实例数组,主要用于初始化和数据校验
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
 * 用于存储ArrayList数据
 */
transient Object[] elementData; // non-private to simplify nested class access

/**
 * 数组列表的大小
 */
private int size;

构造方法

/**
 * 无参构造方法
 */
public ArrayList() {
    // 默认创建一个空实例的数组
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
 * 有参构造方法,创建一个指定长度的数组
 */
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        // 指定长度大于0,创建指定大小的数组
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        // 指定长度等于0,创建空实例数组
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        // 指定长度小于0,则抛出异常
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
/**
 * 有参构造方法,将集合转为数组
 */
public ArrayList(Collection<? extends E> c) {
    // 将集合转为数组,并赋值给elementData
    elementData = c.toArray();
    // 将原集合大小赋值给size,并判断是否等于0
    if ((size = elementData.length) != 0) {
        // 如果c.toArray转换后的对象不是Object数组,将原数组进行拷贝,并给elementData赋值
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // 如果原集合为空,则创建空实例数组
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

主要方法

add(E e)

步骤如下:

  1. 调用calculateCapacity方法计算数组容量,如果数组为空,则获取一个数组容量为10的数组容量;如果数组非空,则获取相应数量的数组容量。
  2. 得到数组容量后,将记录操作数(modCount,作用:快速失败机制)加1。
  3. 判断数组容量是否大于数组实际大小,如果大于,则进行扩容。
    3.1. 获取现有数组长度,计算新的数组容量,默认新数组容量为原数组容量的1.5倍。
    3.2. 如果扩容1.5倍后数组容量还小于实际数组容量,则新数组容量为传入的容量。
    3.3. 如果新数组容量大于Integer最大值减8,再判断传入数组容量是否大于Integer最大值减8,如果大于,数组容量为Integer最大值,如果小于,数据容量为Integer最大值减8。
    3.4. 数组扩容,并将原数据拷贝到新数组中。
  4. 在数组尾部添加元素。
/**
 * 向ArrayList中添加元素
 */
public boolean add(E e) {
    // 扩容操作
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // 在数组末尾添加元素
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

/**
  * 计算数组容量大小
  */
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    // 如果当前数组为空,则比对传入数组容量大小和默认数组容量大小,取最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 如果当前数组不为空,则返回传入的容量大小
    return minCapacity;
}

/**
  * 记录操作数,以及判断是否需要扩容
  */
private void ensureExplicitCapacity(int minCapacity) {
    // 增加操作数
    modCount++;

    // 如果新的数组容量大于当前数组的长度,则进行扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

/**
 * 数组扩容
 */
private void grow(int minCapacity) {
    // 当前数组长度
    int oldCapacity = elementData.length;
    // 计算新的数组容量,默认新数组容量为原数组容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果扩容后的数组容量还小于实际数组容量,则新数组容量为传入的容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 如果新数组容量大于Integer最大值减8,再判断传入数组容量是否大于Integer最大值减8,如果大于,数组容量为Integer最大值,如果小于,数据容量为Integer最大值减8
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 将当前数组拷贝至指定容量大小的新数组,并赋值给当前数组
    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;
}
posted @   云中散客  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示