ArrayList.remove(int index) 删除非末尾元素时,内部在fastRemove()中调用一次System.arraycopy,将elementData[index+1]至末尾元素前移一位,覆盖被删位置,不缩容数组长度。

ArrayList.remove() 内部到底调用哪次 System.arraycopy?
Java 的 ArrayList.remove(int index) 在删除中间或开头元素时,一定会触发一次 System.arraycopy —— 但不是你手动写的那行,而是 JDK 自己在 fastRemove() 里调的。它把 elementData[index + 1] 到末尾的全部元素,向前拷贝一位,覆盖被删位置。这个动作发生在 size 减 1 之后、返回旧值之前。
关键点在于:JDK 不会帮你「缩容」,elementData 数组长度不变,只是逻辑 size 缩了,后续新增可能复用空位。
- 删除索引
i→ 拷贝范围是src: i+1, length: size - i - 1 - 源数组和目标数组都是
elementData,所以是「同一数组内重叠拷贝」,必须用System.arraycopy(Arrays.copyOf或循环赋值都不安全) - 如果删的是最后一个元素(
i == size - 1),则跳过拷贝,只做size--
想手动触发 arraycopy 移动元素,该怎么写才不越界?
如果你绕过 remove(),直接操作 elementData 数组(比如在自定义 List 实现里),必须自己算清拷贝参数。常见错误是 length 算错导致数组越界或漏拷。
假设你要删掉索引 idx 处的元素,当前有效长度为 size:
立即学习“Java免费学习笔记(深入)”;
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 先确认
idx >= 0 && idx ,否则抛 <code>IndexOutOfBoundsException - 拷贝起点:
srcPos = idx + 1 - 拷贝长度:
copyLen = size - idx - 1(不是size - idx) - 目标起点:
destPos = idx - 调用:
System.arraycopy(elementData, idx + 1, elementData, idx, size - idx - 1) - 最后别忘:
size--,并可选地置空尾部引用:elementData[size] = null(防内存泄漏)
为什么不能用 for 循环代替 System.arraycopy?
表面看,写个 for (int i = idx; i 也能动,但它在性能和语义上都输一截:
-
System.arraycopy是 JVM 内建优化指令,对连续内存块做 memcpy 级别搬运,比 Java 层循环快 2–5 倍(尤其大数组) - 循环无法处理「源目标重叠且方向错误」的情况(比如
srcPos 时,必须从后往前赋值),而 <code>arraycopy内部已处理所有重叠场景 - 循环不会自动处理对象引用置 null,容易引发 GC 问题;
arraycopy只搬引用,不干预生命周期 - Android 上低版本 Dalvik 对循环更不友好,
arraycopy是唯一推荐方式
删除多个连续索引时,一次 arraycopy 能搞定吗?
可以,而且应该这么做。比如要删掉 [from, to) 连续区间(左闭右开),等价于把 to 之后的元素整体前移 to - from 位。
设当前 size = n,则:
- 拷贝起点:
srcPos = to - 目标起点:
destPos = from - 拷贝长度:
length = n - to - 调用:
System.arraycopy(elementData, to, elementData, from, n - to) - 更新
size = n - (to - from)
注意:这要求 from ,且区间必须连续。如果要删非连续索引(如删第 1 和第 5 个),仍得两次 <code>arraycopy(或先标记再批量整理),没有通用单次解法。
最易被忽略的是边界检查顺序——必须先校验 to ,再算 <code>n - to,否则 length 为负会导致 ArrayStoreException 或静默失败。

















