system.arraycopy不直接删除元素,而是通过高效移动数据实现逻辑删除,需配合有效长度更新;其核心是前移后续元素并收缩长度,使用时须严格校验索引边界与容量,避免越界或覆盖错误。

System.arraycopy 本身不直接删除元素,而是高效移动数据,配合“逻辑删除”或“覆盖”实现快速移除效果。 它比循环赋值快,尤其适合大数组;但要注意索引边界和目标数组容量,否则容易越界或遗漏。
理解“删除”的本质:不是擦除,而是覆盖+长度收缩
Java 中的数组长度固定,无法真正删减。所谓“删除”,实际是把待删位置之后的元素前移,再减少有效长度(通常用变量维护,或创建新数组)。
- 例如数组
[1,2,3,4,5],要删索引 2(值为 3),就将索引 3、4 的元素(4、5)前移一位 →[1,2,4,5,5],再把有效长度设为 4 -
System.arraycopy(src, srcPos, dest, destPos, length)正是用来完成这段“前移”的核心操作,比 for 循环快且底层优化好
标准删除单个元素的操作步骤
假设有一个 int 数组 arr 和当前有效长度 size,要删索引 index 处的元素:
- 检查
index是否在[0, size)范围内,越界直接抛异常或忽略 - 调用
System.arraycopy(arr, index + 1, arr, index, size - index - 1)—— 把 index+1 开始的剩余元素整体前移一位 - 执行
size--,表示逻辑长度减 1(若需返回新数组,则新建长度为 size-1 的数组并复制)
批量删除多个索引(如按值或条件)的实用技巧
若要删多个不连续位置(比如所有值为 0 的元素),不建议反复调用 arraycopy(每次移动代价高)。更优做法是:
- 先遍历原数组,用双指针:一个读(i),一个写(writeIndex);遇到保留元素就复制到
arr[writeIndex++] - 遍历完后,
writeIndex就是新有效长度,多余部分自然“被覆盖” - 如果必须用 arraycopy 实现批量删,可先排序待删索引(从大到小),再逐个删除——这样前面的删除不会影响后续索引位置
常见陷阱与避坑提醒
用错参数是 arraycopy 出错主因,务必核对:
-
源起始位置 + 长度不能超过源数组长度,否则抛
ArrayIndexOutOfBoundsException - 目标起始位置 + 长度不能超过目标数组长度,尤其当 src == dest 时,容易因重叠覆盖出错(但 arraycopy 对重叠做了安全处理,只要方向正确即可)
- 删除后记得更新业务层的“有效长度”,否则后续操作可能读到旧数据或越界
- 基本类型数组效率高;对象数组用它只是移动引用,不触发 GC,内存释放靠后续无引用











