ArrayList.remove(int index)通过System.arraycopy将index后元素前移一位填补空位,不释放内存但置空尾引用防泄漏,时间复杂度O(n),非线程安全。

Java 中 ArrayList.remove(int index) 方法在删除指定索引处的元素时,确实会调用 System.arraycopy 来移动后续元素,从而“填补”被删除元素留下的空位。这个过程不涉及对象销毁或内存释放,而是数组内数据的偏移拷贝。
为什么需要 System.arraycopy
因为 ArrayList 底层是基于 Object 数组(Object[] elementData)实现的。数组是连续内存块,删除中间某个位置的元素后,逻辑上后面的元素要整体前移一位——但数组本身不能“缩进”,只能靠手动复制来模拟删除效果。
System.arraycopy 是 JVM 优化过的本地方法,比纯 Java 循环拷贝快得多,适合这种批量、连续、同类型的数据搬移。
具体怎么调用 System.arraycopy
以 JDK 17 的 ArrayList 源码为例(其他版本逻辑类似),remove(int index) 关键步骤如下:
立即学习“Java免费学习笔记(深入)”;
HR组织架构与职级体系设计系统。触发场景包括: (1)组织架构设计——设计或调整公司/部门架构、部门划分、汇报关系、决策流; (2)职级体系设计——建立职级序列、职级数量、晋升通道、双通道模型; (3)胜任力模型词典——为岗位序列构建胜任力维度表、行为分级标尺; (4)职级评价(任职资格评定)——用胜任力词典评定...
- 先校验索引是否越界(
index >= size抛IndexOutOfBoundsException) - 取出待删除的元素(用于返回)
- 计算需移动的元素个数:
numMoved = size - index - 1 - 如果
numMoved > 0,就调用:
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
这行代码含义是:
- 从源数组
elementData的index + 1位置开始复制 - 复制
numMoved个元素 - 粘贴到目标数组(也是
elementData)的index位置起
相当于把 [index+1 ... size-1] 整体左移一格,覆盖掉原 index 处的值。
删除后还要清理尾部引用(防内存泄漏)
拷贝完成后,数组末尾多出一个“冗余”引用(原 size-1 位置的元素现在在 size-2,但 elementData[size-1] 还指向旧对象)。为防止 GC 无法回收,JDK 会显式置空:
elementData[--size] = null; // clear to let GC do its work
注意:这只是清除引用,不是释放内存;真正内存回收由垃圾收集器决定。
性能特点与注意事项
- 时间复杂度是 O(n),最坏情况(删第一个)要拷贝全部后续元素
- 不扩容也不缩容数组容量(
capacity不变),只更新size - 多线程环境下非线程安全,同时读写可能引发数据错乱或异常
- 若频繁在头部或中部删除,可考虑
LinkedList(但随机访问慢)或用倒序遍历 +remove(int)减少拷贝次数

















