登录
首页 >  文章 >  java教程

ArrayList底层实现原理解析

时间:2026-03-08 12:02:35 481浏览 收藏

ArrayList是Java中基于动态数组实现的高效列表容器,其底层通过transient Object[]数组存储元素并配合size变量实时追踪有效长度;它采用懒初始化策略——无参构造时不分配空间,首次添加才扩容至默认容量10,后续按1.5倍比例增长(上限为Integer.MAX_VALUE-8),兼顾内存效率与扩展性;凭借数组的连续内存布局,支持O(1)随机访问和末尾增删,但中间位置插入或删除需移动大量元素,时间复杂度达O(n);值得注意的是,它天然不提供线程安全保证,多线程环境下需手动同步。理解这些机制,能帮你避开性能陷阱、写出更健壮的集合操作代码。

在Java里ArrayList是如何工作的_ArrayList底层原理解析

ArrayList 在 Java 中是一个基于数组实现的动态列表,核心特点是“用数组存数据,但能自动变大”。它不是固定长度的普通数组,而是一套封装好的、带扩容逻辑的对象容器。

底层用 Object[] 数组存储元素

ArrayList 的真实数据存在一个叫 elementData 的数组里:

  • 类型是 transient Object[],意味着它不参与默认序列化(序列化时会走自定义逻辑)
  • 所有添加的元素——无论 Integer、String 还是 null——都会被装箱或直接引用,存进这个数组
  • 同时维护一个 size 变量,记录当前实际有几个有效元素(不是数组长度)

初始容量和空数组的两种状态

创建 ArrayList 时,并不总是一上来就分配 10 个位置:

  • 调用无参构造器 new ArrayList()elementData 指向 DEFAULTCAPACITY_EMPTY_ELEMENTDATA(一个空数组)
  • 第一次 add 元素时,才真正初始化为长度为 10 的数组
  • 若用 new ArrayList(0) 或负数容量 → 直接指向 EMPTY_ELEMENTDATA(也是空数组),后续扩容按需增长,不会硬拉到 10

扩容机制:1.5 倍增长,不是翻倍

size == elementData.length,再 add 就会触发扩容:

  • 计算新容量:oldCapacity + (oldCapacity >> 1),即原长 × 1.5(位运算提速)
  • 如果算出来还不够用(比如 minCapacity 要求更高),就直接取 minCapacity
  • 最大不超过 Integer.MAX_VALUE - 8(JVM 数组长度上限预留空间)
  • Arrays.copyOf() 把老数组内容复制到新数组,旧数组丢弃

为什么查得快、中间增删慢?

这是由数组结构决定的天然特性:

  • get(i) / set(i, e):直接通过下标访问内存,O(1)
  • add(e)(末尾):只要不扩容,也是 O(1)
  • add(i, e) / remove(i):要把 i 后面所有元素整体移动,平均 O(n)
  • 不支持线程安全——没加锁,多线程写必须外部同步

终于介绍完啦!小伙伴们,这篇关于《ArrayList底层实现原理解析》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布文章相关知识,快来关注吧!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>