1. 概述
本文将快速讲解如何从 Java 的 List
中移除第一个元素。
我们会针对 List
接口的两种常见实现——ArrayList
和 LinkedList
,分别演示操作方式,并对比其性能差异。✅
2. 初始化 List
首先,我们准备两个包含相同元素的列表,分别基于 ArrayList
和 LinkedList
:
@Before
public void init() {
list.add("cat");
list.add("dog");
pig");
list.add("cow");
list.add("goat");
linkedList.add("cat");
linkedList.add("dog");
linkedList.add("pig");
linkedList.add("cow");
linkedList.add("goat");
}
⚠️ 假设
list
是ArrayList<String>
类型,linkedList
是LinkedList<String>
类型,已提前初始化。
3. ArrayList 中移除首元素
对于 ArrayList
,我们通过索引 0
调用 remove(int index)
方法来删除第一个元素:
@Test
public void givenList_whenRemoveFirst_thenRemoved() {
list.remove(0);
assertThat(list, hasSize(4));
assertThat(list, not(contains("cat")));
}
✅ 这种方式适用于所有 List
接口的实现类,简单粗暴,通用性强。
但要注意:ArrayList
底层是数组,删除第一个元素会导致后续所有元素前移一位,存在数据拷贝开销。
4. LinkedList 中移除首元素
LinkedList
同样支持 remove(0)
,但它还提供了语义更明确、性能更优的专用方法:removeFirst()
。
我们来看实际效果:
@Test
public void givenLinkedList_whenRemoveFirst_thenRemoved() {
linkedList.removeFirst();
assertThat(linkedList, hasSize(4));
assertThat(linkedList, not(contains("cat")));
}
✅ removeFirst()
不仅代码意图更清晰,而且在 LinkedList
上性能最佳。
5. 时间复杂度对比
虽然两个操作结果一致,但底层效率天差地别 ❌
实现类 | 方法 | 时间复杂度 | 原因说明 |
---|---|---|---|
ArrayList |
remove(0) |
O(n) | 数组元素需整体前移,数据拷贝耗时随长度增长 |
LinkedList |
removeFirst() |
O(1) | 仅需调整头指针指向下一个节点,与列表长度无关 |
📌 关键点:
ArrayList
删除首元素 = 所有元素左移一位 = 大量System.arraycopy
调用 = 越长越慢LinkedList
删除首元素 = 修改head
指针 = 固定几步操作 = 始终飞快
💡 如果你频繁在头部增删元素,
LinkedList
是更合适的选择;若只是偶尔操作,ArrayList
依然更省空间且缓存友好。
6. 总结
本文演示了如何从 List
中移除第一个元素,并重点对比了 ArrayList
与 LinkedList
在该操作上的性能差异:
- ✅ 通用做法:
list.remove(0)
- ✅ 最佳实践(LinkedList):使用
removeFirst()
提升可读性和性能 - ⚠️ 踩坑提醒:高频首删场景下避免使用
ArrayList
,否则可能引发性能瓶颈
完整示例代码已上传至 GitHub:https://github.com/javatutorial/collections-list