ArrayList源码分析

本文深入解析了Java中ArrayList的工作原理,包括其内部实现机制、如何动态扩展数组长度、添加和删除元素的操作细节等。此外还介绍了优化技巧如trimToSize()方法的使用。

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

常用集合类

1. ArrayList 源码分析

ArrayList内部使用的是一个数组来保存数据. 主要是利用 Arrays.copyOf() 方法来动态扩展数组长度. ArrayList还是相对简单的.

1.1 ArrayList原理

ArrayList内部使用了一个 Object[] 来存储数据。

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

ArrayList初始化时可以指定数组大小

// 指定数组大小,初始化ArrayList.
public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
}

如果不指定大小则, 默认是空数组

// 默认空数组定义
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 无参数构造方法
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

1.2 ArrayList 优化函数.

当不在添加元素时, 将剩余的空间释放掉.

public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}

1.3 增加元素API

默认情况下元素添加到最后一个元素的后面

public boolean add(E e) {
    // 设置数组长度, 确保数组够长.如果不够会自动增加长度.
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // size是当前元素个数. 下面这句代码是将元素添加到最后.
    elementData[size++] = e;
    return true;
}

下面来看下 ensureCapacityInternal 更新数组实际长度的方法.

private void ensureCapacityInternal(int minCapacity) {
    modCount++;
    // 判断当前数组长度是否小于数组长度. 如果不小于则增加长度.
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

下面来看下 grow 方法源码.

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);
}

上面的代码非常简单首先将数组长度增加2倍, 如果还是不够长度, 则直接将长度增加到minCapacity.之后还要比较此时长度是否超过最大长度.处理过程如下

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

在指定位置添加元素API

public void add(int index, E element) {
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // 将要插入位置以后的元素, 整体后移.
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    // 在index位置插入.
    elementData[index] = element;
    size++;
}

1.4 删除元素API

remove(index)

public E remove(int index) {
    rangeCheck(index);

    modCount++;
    // 获取要删除元素值.
    E oldValue = elementData(index);
    // 获取要删除元素的个数.
    int numMoved = size - index - 1;
    // 将index 之后的元素前移
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    // 将最后一个位置设置为null
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

ArrayList的结构相对简单.也容易理解.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值