JDK 8 ArrayList 详解及详细源码展示

JDK 8 ArrayList 详解及详细源码展示

JDK 8 的 ArrayList 是 Java 集合框架中的核心实现,基于 动态数组 实现,支持快速随机访问和动态扩容。本文结合源码剖析其设计哲学、核心实现及性能优化技术。

一、核心设计目标:动态数组与快速随机访问
1.1 动态数组特性
  • 自动扩容:当元素数量超过当前容量时,自动扩容为原来的 1.5 倍。
  • 容量缩减:通过 trimToSize() 方法可手动缩减容量。
1.2 快速随机访问
  • 索引直接映射:通过 get(int index) 方法,时间复杂度为 O(1)。
  • 内存连续性:底层基于数组实现,元素在内存中连续存储。
二、源码核心类结构
// java.util.ArrayList.java
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
    // 默认初始容量
    private static final int DEFAULT_CAPACITY = 10;
    // 空数组(用于延迟初始化)
    private static final Object[] EMPTY_ELEMENTDATA = {};
    // 默认空数组(当用户使用无参构造时使用)
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    // 底层数组
    transient Object[] elementData;
    // 元素数量
    private int size;
    // 修改次数(用于快速失败机制)
    protected transient int modCount = 0;

    // 构造方法
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
        }
    }
}
三、核心方法源码解析
3.1 add 方法
public boolean add(E e) {
    // 确保容量足够
    ensureCapacityInternal(size + 1);
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(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;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 复制数组
    elementData = Arrays.copyOf(elementData, newCapacity);
}
3.2 get 方法
public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}

private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}
3.3 remove 方法
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; // 清除引用,帮助 GC
    return oldValue;
}
四、关键优化技术
4.1 动态扩容策略
  • 扩容因子:默认扩容为原来的 1.5 倍(newCapacity = oldCapacity + (oldCapacity >> 1))。
  • 容量限制:最大容量为 Integer.MAX_VALUE - 8(避免内存溢出)。
4.2 内存局部性优化
  • 连续内存:元素在内存中连续存储,提升缓存命中率。
  • 数组复制:通过 System.arraycopy 优化数组复制性能。
4.3 快速失败机制
  • 修改计数器:通过 modCount 字段检测并发修改。
  • 迭代器检查:在迭代过程中,若 modCount 变化,抛出 ConcurrentModificationException
五、典型应用场景
5.1 基础操作
// 创建 ArrayList
List<String> list = new ArrayList<>();

// 添加元素
list.add("A");
list.add("B");

// 随机访问
String element = list.get(1); // "B"

// 删除元素
list.remove(0);
5.2 批量操作
// 批量添加
List<String> subList = Arrays.asList("C", "D");
list.addAll(subList);

// 批量删除
list.removeAll(subList);

// 范围删除
list.subList(0, 2).clear();
5.3 性能优化
// 预分配容量(避免频繁扩容)
List<String> list = new ArrayList<>(1000);

// 手动缩减容量
list.trimToSize();
六、总结

JDK 8 的 ArrayList 通过动态数组、快速随机访问、自动扩容等核心技术,实现了高效的顺序存储。其源码实现深刻体现了数据结构与算法的精髓:

  1. 动态扩容:平衡时间和空间复杂度,减少频繁内存分配开销。
  2. 内存局部性:连续内存布局提升缓存命中率。
  3. 快速失败:通过 modCount 检测并发修改,保障迭代安全。

实际开发中,建议优先使用 ArrayList,但在多线程场景下需改用 CopyOnWriteArrayList 或通过 Collections.synchronizedList 包装。深入理解其源码,有助于设计高性能的 Java 应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值