ArrayList的size是当前实际元素个数,调用size()方法获取,时间复杂度O(1);capacity是底层数组长度,无公开方法获取,可通过反射或扩容规律估算,但反射不推荐用于生产环境。

ArrayList 的大小(size)和容量(capacity)是两个不同概念:size 是当前实际存储的元素个数,capacity 是底层数组能容纳的最大元素数量;获取 size 很简单,但 capacity 是私有字段,不能直接访问,需通过反射或间接方式估算。
如何获取当前元素个数(size)
调用 size() 方法即可,时间复杂度 O(1),返回的是当前集合中已添加的元素个数:
- 无论是否发生过扩容,
size()始终反映真实数据量 - 清空后调用
clear()会将 size 置为 0,但底层数组不会缩容 - 注意:
size() == 0不代表底层数组为空,只是逻辑上无元素
怎么知道当前容量(capacity)
ArrayList 没有公开的 capacity() 方法。capacity 存储在私有字段 elementData 的数组长度中,可通过以下方式获取:
- 反射读取:
field = ArrayList.class.getDeclaredField("elementData"); field.setAccessible(true); Object[] arr = (Object[]) field.get(list); int capacity = arr.length; - 间接估算:新建空 ArrayList 默认容量为 10;每次扩容按 1.5 倍增长(如 10 → 15 → 22 → 33…),可结合
size()和扩容规律反推 - 不推荐生产环境用反射——破坏封装、存在兼容风险(如 JDK 17+ 对反射限制更严)
容量优化的关键时机与做法
容量优化核心是避免频繁扩容(影响性能)和过度占内存(浪费空间)。重点在初始化和批量添加时干预:
立即学习“Java免费学习笔记(深入)”;
- 预估数据量,用带初始容量的构造方法:
new ArrayList(expectedSize),减少自动扩容次数 - 批量添加前,若已知总数,可先调用
ensureCapacity(minCapacity)预分配空间 - 长期只读且不再增删的列表,可用
trimToSize()缩容到底层数组刚好容纳当前元素,释放冗余内存 - 注意:
trimToSize()会触发一次数组复制,仅在内存敏感场景下使用,非必要不频繁调用
常见误区提醒
别把 size 当 capacity,也别误以为 capacity 会自动收缩:
-
remove()或clear()后 capacity 不变,仍保持扩容后的最大值 - 反复 add/remove 小量数据,可能导致 capacity 远大于实际 size,造成内存浪费
- 并发环境下 ArrayList 不安全,size 和容量状态可能不一致,应改用
CopyOnWriteArrayList或外部同步


















