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
      )。

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

相关推荐
爱编程的涵崽1 分钟前
PyTorch——从入门到精通:PyTorch简介与安装(最新版)【PyTorch系统学习】
人工智能·pytorch·python·深度学习
建群新人小猿1 小时前
退款成功订阅消息点击后提示订单不存在
java·开发语言·前端
要开心吖ZSH1 小时前
关于Java合并多个Excel中的数据【该数据不是常规列表】,并入库保存的方案
java·excel
飞翔的佩奇1 小时前
maven手动上传jar到私服仓库:mvn deploy:deploy-file命令
java·maven·jar·仓库·私服·deploy
朝屯暮蒙vi2 小时前
IntelliJ IDEA新建项目或导入未识别为maven解决
java·maven·intellij-idea
《源码好优多》2 小时前
基于Java Springboot甘肃旅游管理系统
java·spring boot·旅游
我叫czc2 小时前
【python笔记03】《类》
开发语言·笔记·python
菩提祖师_2 小时前
基于Java的旅游类小程序开发与优化
java·开发语言·旅游
墨绿色的摆渡人2 小时前
用 Python 从零开始创建神经网络(五):损失函数(Loss Functions)计算网络误差
人工智能·python·深度学习·神经网络
万叶学编程3 小时前
HBase 开发:使用Java操作HBase
java·数据库·hbase