ArrayList源码分析 add(E e)

本文详细解析了Java中ArrayList的add方法实现原理。介绍了ArrayList如何通过调整容量来存储新增元素,并确保内部数组能够容纳更多的数据。文章还深入探讨了ArrayList如何在达到初始容量限制时进行扩容,以及扩容过程中涉及的内存分配和数据复制过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

add(E e)方法

*存储ArrayList元素的数组缓冲区。
* ArrayList的容量是这个数组缓冲区的长度。任何
*带有elementData的空ArrayList == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
*当添加第一个元素时,*将被扩展到DEFAULT_CAPACITY。
 
transient Object[] elementData;

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

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

private static final int DEFAULT_CAPACITY = 10;

  //默认0
 private int size;
  




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 void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(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++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

  private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        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;
    }

//Arrays 工具类方法
public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

 

### Java `ArrayList` 源码详解 #### 一、类定义与继承关系 `ArrayList` 是实现了 `List` 接口的一个动态数组实现。其内部维护了一个对象数组作为存储容器,允许随机访问元素并支持高效的迭代操作[^1]。 ```java public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L; } ``` #### 二、底层数据结构 `ArrayList` 的核心在于它使用了 Object 数组来保存所有的元素: ```java transient Object[] elementData; // non-private to simplify nested class access ``` 当创建一个新的 `ArrayList` 实例时,默认容量为空,即不分配任何空间给 `elementData`;只有在第一次添加元素时才会初始化默认大小为 10 的数组[^2]。 #### 三、扩容机制 每当向列表中追加新项而当前容量不足以容纳这些新增项目时,就会触发一次扩容过程。具体来说,会按照现有长度的一半增加新的容量,并将旧的数据复制到更大的内存区域中去[^3]。 ```java private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; ... elementData = Arrays.copyOf(elementData, newCapacity); } ``` #### 四、常用方法解析 ##### 添加元素 (`add(E e)`) 此方法用于在列表末尾插入指定元素。如果必要的话还会调用前面提到过的 `grow()` 函数来进行自动扩展。 ```java public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } ``` ##### 获取元素 (`get(int index)`) 通过索引快速定位所需位置上的值,时间复杂度 O(1),因为可以直接计算出目标地址。 ```java public E get(int index) { rangeCheck(index); return elementData(index); } ``` ##### 删除元素 (`remove(int index)`) 移除特定下标的成员并将后续部分向前移动一位填补空缺,平均情况下需要线性扫描整个序列完成调整工作。 ```java public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); 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 return oldValue; } ``` #### 五、遍历方式 除了传统的基于索引循环外,还可以利用增强型for-each语句或是 Iterator 来高效地处理大量连续排列的对象实例集合。 ```java // 使用Iterator遍历 Iterator<String> it = list.iterator(); while(it.hasNext()){ String str = it.next(); } // 或者更简洁的方式 for(String s : list){ } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值