CodeGym /课程 /JAVA 25 SELF /List:ArrayList 与 LinkedList,基础操作

List:ArrayList 与 LinkedList,基础操作

JAVA 25 SELF
第 26 级 , 课程 1
可用

1. 类 ArrayList

在 Java 中,接口 List 是一种契约:“我是一个有序的元素集合,你可以通过编号(索引)获取元素”。

列表(List)的关键特性:

  • 元素按确定的顺序存储(不同于 Set)。
  • 可以存储重复元素(例如:两次出现 "Vasya")。
  • 可以按索引访问元素:第一个元素索引为 0,第二个为 1,以此类推。
  • 可以在列表的任何位置添加、删除元素。

接口 List 最常见的实现是 ArrayList。它在内部使用普通数组,随着数据增多自动扩容。

如何创建 ArrayList

import java.util.ArrayList;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        // 创建字符串列表
        List<String> students = new ArrayList<>();
    }
}

说明

  • List<String> 是“字符串列表”类型的变量。通过接口来声明变量,通过具体类(ArrayList)来创建对象。
  • 尖括号 <String> 指定列表元素的类型(泛型,generics)。

ArrayList(以及任何 List)的常用方法:

  • add(element) —— 在列表末尾添加元素。
  • add(index, element) —— 在指定索引处插入元素。
  • get(index) —— 按索引获取元素。
  • set(index, element) —— 按索引替换元素。
  • remove(index) —— 按索引删除元素。
  • remove(Object) —— 删除与传入对象相等的第一个元素。
  • size() —— 获取列表中元素的数量。

示例:操作学生列表

import java.util.ArrayList;
import java.util.List;

public class StudentListDemo {
    public static void main(String[] args) {
        List<String> students = new ArrayList<>();

        // 添加学生
        students.add("Vasya");
        students.add("Petya");
        students.add("Masha");

        // 输出所有学生
        System.out.println("学生列表: " + students);

        // 获取第一个学生
        String first = students.get(0);
        System.out.println("第一个学生: " + first);

        // 修改第二个学生的名字
        students.set(1, "Pavel");
        System.out.println("修改后: " + students);

        // 删除Masha
        students.remove("Masha");
        System.out.println("删除Masha后: " + students);

        // 列表大小
        System.out.println("学生总数: " + students.size());
    }
}

结果:

学生列表: [Vasya, Petya, Masha]
第一个学生: Vasya
修改后: [Vasya, Pavel, Masha]
删除Masha后: [Vasya, Pavel]
学生总数: 2

这与我们的应用有什么关系?
假设我们有一个学生任务管理应用。现在可以用 List<String> 来存储任务列表,而不是用数组,并且可以动态添加新任务。

2. 类 LinkedList:当插入和删除的速度更重要

LinkedList 是列表的另一种实现。它是由双向节点串成的链,每个节点都知道前驱和后继。就像一列火车:在中间插入“车厢”很快,不需要重排整个车列。

创建 LinkedList

import java.util.LinkedList;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        List<String> tasks = new LinkedList<>();
    }
}

LinkedList 的特点

  • 在列表开头和中间进行插入、删除速度快。
  • 按索引访问较慢(要找到第 100 个元素,需要沿链逐个前进)。
  • 适合不仅在末尾,也经常在开头或中间添加/删除元素的场景。

示例:使用 LinkedList

import java.util.LinkedList;
import java.util.List;

public class TaskListDemo {
    public static void main(String[] args) {
        List<String> tasks = new LinkedList<>();

        tasks.add("起床");
        tasks.add("吃早餐");
        tasks.add("去上课");

        // 在开头添加任务
        tasks.add(0, "设定闹钟");

        System.out.println("任务列表: " + tasks);

        // 删除第一项任务(最早的一项)
        tasks.remove(0);

        System.out.println("删除第一项任务后: " + tasks);
    }
}

3. 对比 ArrayListLinkedList

指标
ArrayList
LinkedList
底层结构 数组 双向链表
按索引的快速访问 是 (O(1)) 否 (O(n))
在开头/中间快速插入/删除 否 (O(n)) 是 (O(1) — 如果有引用)
在末尾快速插入/删除 是 (通常为 O(1)) 是 (O(1))
内存 占用更少内存 占用更多(需要额外存储前后指针)
典型场景 频繁按索引访问 频繁插入/删除

简单规则:

  • 需要按编号快速访问 —— 使用 ArrayList
  • 经常在开头或中间添加/删除 —— 使用 LinkedList

4. 列表的常见操作

遍历列表元素

普通 for 循环

for (int i = 0; i < students.size(); i++) {
    System.out.println("学生 #" + i + ": " + students.get(i));
}

for-each 循环(最常用的方式)

for (String name : students) {
    System.out.println("姓名: " + name);
}

Lambda 表达式(Java 8+)

students.forEach(name -> System.out.println("姓名: " + name));

查找元素

  • contains(element) —— 如果列表中存在该元素则返回 true
  • indexOf(element) —— 返回元素第一次出现的索引;若未找到则返回 -1
if (students.contains("Vasya")) {
    System.out.println("Vasya在列表中!");
}
int index = students.indexOf("Vasya");
System.out.println("Vasya的索引: " + index);

清空列表

clear() —— 删除所有元素。

students.clear();
System.out.println("清空后的列表: " + students);

5. 何时使用 ArrayList,何时使用 LinkedList

可以这样思考:ArrayList 适用于需要按索引快速访问元素,且列表不经常变更的场景。例如很长的用户列表或消息历史——以读取为主。

相反,LinkedList 在你经常在开头/中间插入或删除元素时更有用。典型如队列、栈或操作撤销历史。

在实践中最常用的还是 ArrayList。而 LinkedList 更像是“备用工具”:平时放在工具箱里,但有时恰好能派上用场。

6. 使用列表时的常见错误

错误 1:索引越界。 最常见的情况是访问不存在的索引。如果列表只有三个元素,却写了 students.get(5),会抛出 IndexOutOfBoundsException。访问前请检查 size()

错误 2:遍历时删除元素。 在使用 for-each 遍历并同时删除元素时,会触发 ConcurrentModificationException。对于复杂的删除操作,请使用按索引的循环或 Iterator

错误 3:错误的对象比较。 如果你存储的是自定义对象(例如 Student),containsremove 依赖 equals。若未重写它,比较将基于引用而非内容。

错误 4:使用原生类型(raw types)。 不要写 List list = new ArrayList() —— 请始终指定元素类型:List<String> list = new ArrayList<>()。泛型能避免错误并让代码更清晰。

评论 (1)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
ncksllpo 级别 44,Cherkasy,Ukraine
16 二月 2026
🍟