java arraylist 在中间插入或删除元素之所以慢,根本原因是其底层基于数组实现,必须通过 system.arraycopy() 将目标位置之后的所有元素整体前移或后移,以填补空缺或腾出空间。这种操作的时间复杂度为 o(n),且涉及内存的批量拷贝,随着列表规模增大,性能损耗会显著增加。

为什么尾部操作快而中间操作慢
尾部操作(如 add(E e))通常只需检查容量并追加元素,时间复杂度为 O(1);而中间操作需要移动大量数据。以下代码演示了两种操作的耗时差异:
import java.util.ArrayList;
import java.util.List;
public class ArrayListPerformance {
public static void main(String[] args) {
List<integer> list = new ArrayList();
// 填充100,000个元素
for (int i = 0; i <p>预期结果:尾部添加耗时极短(微秒级),中间插入耗时较长(毫秒级),因为中间插入触发了约50,000次元素位移。</p>
<p><img src="https://img.php.cn/upload/article/001/242/473/179454506724912.png?x-oss-process=image/resize,p_40" alt="Java ArrayList 为什么中间插入删除慢"></p>
<h2>扩容机制如何加剧中间插入的性能开销</h2>
<p>当 <code>ArrayList</code> 容量不足时,会触发扩容:创建新数组(通常为原容量的1.5倍),并将旧数组所有元素复制到新数组。若在中间插入导致容量不足,除了常规的元素位移外,还需执行一次全量复制,进一步放大性能损耗。以下代码展示扩容时的行为:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill12680" title="JavaScript 开发专家"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dee630206.jpg" alt="JavaScript 开发专家" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill12680" title="JavaScript 开发专家" class="overflowclass">JavaScript 开发专家</a>
<p class="overflowclass">掌握包含 ES6+、异步模式和 Node.js API 的现代 JavaScript。处理 Promise、事件循环和浏览器/Node 兼容性。在 JavaSc</p>
</div>
<a rel="nofollow" href="/xiazai/skill12680" title="JavaScript 开发专家" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<pre class="brush:php;toolbar:false;">import java.util.ArrayList;
import java.util.List;
public class ArrayListResize {
public static void main(String[] args) {
List<string> list = new ArrayList(2); // 初始容量2
list.add("A");
list.add("B");
// 此时容量为2,下次插入将触发扩容
list.add(1, "X"); // 在索引1处插入,需先位移,再可能扩容
System.out.println(list); // [A, X, B]
}
}</string>
预期输出:[A, X, B]。该操作涉及:1) 将索引1及之后的元素(即"B")后移一位;2) 若当前容量已满,则扩容并复制所有元素;3) 在空出的位置写入"X"。

频繁中间删除导致的内存碎片与性能下降
频繁在中间删除元素不仅带来 O(n) 的位移开销,还会导致底层数组的有效利用率降低。虽然 ArrayList 不会自动缩小数组容量,但反复删除会使大量元素被“逻辑移除”,实际仍占用内存空间。以下代码验证删除后的状态:
import java.util.ArrayList;
import java.util.List;
public class ArrayListDelete {
public static void main(String[] args) {
List<integer> list = new ArrayList();
for (int i = 0; i )list).size()); // 注意:无直接获取capacity方法,此处用size模拟逻辑大小
}
}</integer>
预期输出:Size为900,但底层数组容量仍为1000(或更大,取决于扩容历史)。这意味着有100个槽位为空,造成内存浪费。若需优化,可调用 trimToSize() 释放多余容量,但该操作本身也是 O(n) 的复制过程。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










