Java LinkedList 详解

LinkedList 是 Java 集合框架中常用的数据结构之一,位于 java.util 包中。它实现了 ListDequeQueue 接口,是一个双向链表结构,适合频繁的插入和删除操作。


1. LinkedList 的特点

  1. 数据结构:基于双向链表实现,每个节点包含:

    • 数据部分(存储值)。
    • 前驱指针(指向前一个节点)。
    • 后继指针(指向后一个节点)。
  2. 实现接口

    • List:支持按索引随机访问、插入和删除操作。
    • Deque:支持双端队列操作。
    • Queue:支持队列操作。
  3. 操作特性

    • 插入和删除效率高 :在头部或尾部插入和删除操作的时间复杂度为 O ( 1 ) O(1) O(1)。
    • 随机访问效率低 :需要遍历链表查找元素,时间复杂度为 O ( n ) O(n) O(n)。

2. LinkedList 的构造方法

LinkedList 提供了以下两种构造方法:

  1. 无参构造

    java 复制代码
    LinkedList<Integer> list = new LinkedList<>();

    创建一个空的链表。

  2. 带集合参数的构造

    java 复制代码
    List<Integer> arrayList = Arrays.asList(1, 2, 3);
    LinkedList<Integer> list = new LinkedList<>(arrayList);

    使用另一个集合初始化链表。


3. 常用方法

LinkedList 继承了 ListDeque 的所有方法。以下是常用方法的分类及示例:

3.1 添加元素
  • 尾部添加

    java 复制代码
    list.add(10);  // 在尾部添加元素
  • 指定位置添加

    java 复制代码
    list.add(1, 20);  // 在索引 1 处插入元素 20
  • 头部添加

    java 复制代码
    list.addFirst(5);  // 在头部添加元素
  • 尾部添加

    java 复制代码
    list.addLast(15);  // 在尾部添加元素

3.2 删除元素
  • 删除头部元素

    java 复制代码
    list.removeFirst();  // 删除并返回头部元素
  • 删除尾部元素

    java 复制代码
    list.removeLast();  // 删除并返回尾部元素
  • 删除指定位置元素

    java 复制代码
    list.remove(2);  // 删除索引 2 处的元素
  • 删除指定值

    java 复制代码
    list.remove(Integer.valueOf(10));  // 删除第一个匹配值为 10 的元素

3.3 获取元素
  • 头部或尾部元素

    java 复制代码
    list.getFirst();  // 返回头部元素
    list.getLast();   // 返回尾部元素
  • 指定位置元素

    java 复制代码
    list.get(2);  // 返回索引 2 处的元素

3.4 检查元素
  • 是否包含某个元素

    java 复制代码
    list.contains(20);  // 检查链表是否包含值为 20 的元素
  • 是否为空

    java 复制代码
    list.isEmpty();  // 检查链表是否为空

3.5 迭代元素
  • 普通 for 循环

    java 复制代码
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
  • 增强 for 循环

    java 复制代码
    for (Integer num : list) {
        System.out.println(num);
    }
  • 使用迭代器

    java 复制代码
    Iterator<Integer> iterator = list.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }

3.6 双端队列操作

LinkedList 实现了 Deque 接口,支持双端队列的操作。

  • 入队(头部或尾部)

    java 复制代码
    list.offerFirst(1);  // 在头部添加元素
    list.offerLast(2);   // 在尾部添加元素
  • 出队(头部或尾部)

    java 复制代码
    list.pollFirst();  // 删除并返回头部元素
    list.pollLast();   // 删除并返回尾部元素

3.7 栈操作

LinkedList 也可以用作栈,支持栈的基本操作。

  • 压栈

    java 复制代码
    list.push(10);  // 将元素压入栈顶(头部)
  • 出栈

    java 复制代码
    list.pop();  // 弹出栈顶元素(头部)

4. 示例代码

以下是一个综合使用 LinkedList 的示例:

java 复制代码
import java.util.LinkedList;

public class LinkedListExample {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();

        // 添加元素
        list.add(10);
        list.add(20);
        list.add(30);
        list.addFirst(5);
        list.addLast(40);
        System.out.println("链表内容: " + list);

        // 删除元素
        list.removeFirst();
        list.removeLast();
        list.remove(Integer.valueOf(20));
        System.out.println("删除元素后的链表: " + list);

        // 获取元素
        System.out.println("头部元素: " + list.getFirst());
        System.out.println("尾部元素: " + list.getLast());

        // 检查元素
        System.out.println("是否包含 30: " + list.contains(30));

        // 使用栈操作
        list.push(50);  // 压栈
        System.out.println("压栈后的链表: " + list);
        list.pop();     // 出栈
        System.out.println("出栈后的链表: " + list);

        // 使用队列操作
        list.offerFirst(5);  // 入队头部
        list.offerLast(60);  // 入队尾部
        System.out.println("使用队列操作后的链表: " + list);

        // 遍历元素
        System.out.println("遍历链表:");
        for (Integer num : list) {
            System.out.println(num);
        }
    }
}

输出

复制代码
链表内容: [5, 10, 20, 30, 40]
删除元素后的链表: [10, 30]
头部元素: 10
尾部元素: 30
是否包含 30: true
压栈后的链表: [50, 10, 30]
出栈后的链表: [10, 30]
使用队列操作后的链表: [5, 10, 30, 60]
遍历链表:
5
10
30
60

5. LinkedList 的时间复杂度

操作 时间复杂度 原因
插入(头部/尾部) O ( 1 ) O(1) O(1) 双向链表操作,直接修改指针即可
删除(头部/尾部) O ( 1 ) O(1) O(1) 双向链表操作,直接修改指针即可
按索引访问元素 O ( n ) O(n) O(n) 需要从头部或尾部遍历到指定位置
查找某个元素 O ( n ) O(n) O(n) 遍历整个链表
插入/删除(中间位置) O ( n ) O(n) O(n) 需要先遍历找到位置,然后修改指针

6. LinkedList 的优缺点

优点
  1. 适合频繁插入和删除操作。
  2. 实现了多种接口(ListDequeQueue),功能强大。
  3. 支持双端操作(头部和尾部操作都高效)。
缺点
  1. 随机访问性能差,需要遍历链表,时间复杂度为 O ( n ) O(n) O(n)。
  2. 占用额外的内存空间(指针存储前驱和后继节点)。

7. 总结

  • 适用场景

    • 数据插入和删除频繁的场景(如队列、栈操作)。
    • 数据大小较小,链表的额外内存开销可以接受。
  • 不适用场景

    • 随机访问频繁的场景(推荐使用 ArrayList
      )。

通过合理选择数据结构,可以根据具体需求提高程序性能和代码效率。

相关推荐
0和1的舞者22 分钟前
Spring AOP详解(一)
java·开发语言·前端·spring·aop·面向切面
蒜丶23 分钟前
Windows 11 22H2 跳过联网激活
windows
Wang153026 分钟前
Java多线程死锁排查
java·计算机网络
智航GIS38 分钟前
8.2 面向对象
开发语言·python
小小星球之旅1 小时前
CompletableFuture学习
java·开发语言·学习
蹦蹦跳跳真可爱5891 小时前
Python----大模型(GPT-2模型训练加速,训练策略)
人工智能·pytorch·python·gpt·embedding
xwill*1 小时前
π∗0.6: a VLA That Learns From Experience
人工智能·pytorch·python
jiayong231 小时前
知识库概念与核心价值01
java·人工智能·spring·知识库
皮皮林5512 小时前
告别 OOM:EasyExcel 百万数据导出最佳实践(附开箱即用增强工具类)
java
还不秃顶的计科生2 小时前
LeetCode 热题 100第二题:字母易位词分组python版本
linux·python·leetcode