ArrayList 的底层原理

以下是 ArrayList 的底层原理的详细介绍,结合其动态数组实现、扩容机制、核心操作及线程安全性等方面展开:


一、底层结构与初始化

ArrayList 的底层基于 Object 数组 elementData 实现,通过动态扩容机制支持元素的动态增删。
核心属性
elementData:存储元素的数组,初始为空数组(无参构造时)。
size:记录当前元素数量(非数组长度)。
初始容量
默认初始容量为 10(首次添加元素时触发,在空参构造时创建一个ArrayList时默认是容量为0的)。
• 可通过构造器指定初始容量(如 new ArrayList<>(50)),避免频繁扩容。


二、动态扩容机制

当添加元素导致 size + 1 > elementData.length 时触发扩容:

  1. 扩容规则
    新容量 = 旧容量 × 1.5(通过 oldCapacity + (oldCapacity >> 1) 实现右移运算)。
    • 若一次性添加多个元素(如 addAll()),直接扩容至 Math.max(原容量 × 1.5, 实际所需容量)
  2. 扩容实现
    • 调用 Arrays.copyOf() 将旧数组数据复制到新数组,旧数组被 GC 回收。
    最大容量限制Integer.MAX_VALUE - 8(避免内存溢出)。

三、核心操作的时间复杂度

操作时间复杂度说明
尾部追加元素O(1) 均摊扩容时需 O(n),但均摊后为 O(1)。
随机访问O(1)直接通过数组索引访问(如 get(index))。
插入/删除元素O(n)需移动后续元素(如 add(index, e)remove(index))。
遍历O(n)顺序访问数组元素。

四、线程安全性与替代方案

非线程安全
多线程并发修改会导致数据不一致或 ConcurrentModificationException(通过 modCount 检测修改次数)。
解决方案
• 使用 Collections.synchronizedList(new ArrayList<>()) 包装为同步列表。
• 高并发读场景下,采用 CopyOnWriteArrayList(写时复制,牺牲一致性)。


五、与 Vector 的对比

特性ArrayListVector
线程安全性非线程安全线程安全(方法用 synchronized 修饰)。
扩容机制扩容 1.5 倍扩容 2 倍。
性能更高(无锁开销)较低(锁竞争)。
初始容量默认 10(延迟初始化)默认 10(直接初始化)。

六、性能优化建议

  1. 预分配容量
    • 若已知数据量,通过构造器指定初始容量(如 new ArrayList<>(1000)),减少扩容次数。
  2. 尾部操作优先
    • 避免频繁在中间插入/删除元素,尽量使用 add(e)remove(size-1)
  3. 慎用快速失败迭代器
    • 遍历时若需修改集合,改用 Iterator.remove() 或复制新集合操作。

七、源码关键方法解析

  1. 添加元素(add(e)

    public boolean add(E e) {
        ensureCapacityInternal(size + 1); // 检查扩容
        elementData[size++] = e; // 尾部插入
        return true;
    }
    

    ensureCapacityInternal() 确保容量足够,触发扩容逻辑。

  2. 扩容(grow()

    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍扩容
        elementData = Arrays.copyOf(elementData, newCapacity); // 复制数组
    }
    

总结

ArrayList 通过动态数组实现高效的随机访问,但插入/删除中间元素性能较低,适合读多写少的场景。在多线程环境下需使用同步包装类或并发集合替代。合理预分配容量和优化操作位置可显著提升性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值