1. 概述

本文将快速讲解如何从 Java 的 List 中移除第一个元素。

我们会针对 List 接口的两种常见实现——ArrayListLinkedList,分别演示操作方式,并对比其性能差异。✅

2. 初始化 List

首先,我们准备两个包含相同元素的列表,分别基于 ArrayListLinkedList

@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");
}

⚠️ 假设 listArrayList<String> 类型,linkedListLinkedList<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 中移除第一个元素,并重点对比了 ArrayListLinkedList 在该操作上的性能差异:

  • ✅ 通用做法:list.remove(0)
  • ✅ 最佳实践(LinkedList):使用 removeFirst() 提升可读性和性能
  • ⚠️ 踩坑提醒:高频首删场景下避免使用 ArrayList,否则可能引发性能瓶颈

完整示例代码已上传至 GitHub:https://github.com/javatutorial/collections-list


原始标题:Remove the First Element from a List