Java LinkedList 详解

devtools/2024/11/19 9:11:21/

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

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


http://www.ppmy.cn/devtools/135171.html

相关文章

QT中使用图表之QChart绘制柱状图

绘制条形&#xff08;柱状&#xff09;图&#xff0c;系列选择条形系列QBarSeries x轴选择条形图的种类轴QBarCategoryAxis 1、创建图表视图 //1、创建图表视图 QChartView * view new QChartView(this); //开启抗锯齿 view -> setRenderHint(QPainter::Antialiasing); …

vue自定义指令--一键复制

vue项目中想要实现点击按钮一键复制&#xff0c;可以通过vue的自定义指令directive来实现。 一、新建directive.js文件 新建directive.js文件&#xff0c;用于定义所有的自定义指令。 import { Toast } from vant;const directive {// 一键复制copy:{bind (el, { value }) …

日志采样标记算法

从日志中提取特征值: {0: (LDAP Built with OpenLDAP LDAP SDK, :), 1: (LDAP SSL support unavailable, :), 2: (suEXEC mechanism enabled lili wrapper /usr/sbin/suexec, ()/:), 3: (Digest generating secret for digest authentication ..., .:), 4: (Digest done…

第十一章 对Stream流的聚合函数处理

目录 一、对流中数据进行聚合计算 二、对流中数据进行分组 三、对流中数据进行多级分组 四、对流中数据进行分区 4.1. 使用方式及代码 4.2. 分区于分组的区别 分区&#xff08;Partitioning&#xff09; 分组&#xff08;Grouping&#xff09; 实际应用场景 五、对流…

20-大模型外挂知识库优化——负样本样本挖掘篇

大模型外挂知识库优化——负样本样本挖掘篇 一、为什么需要构建负难样本&#xff1f; 在各类检索任务中&#xff0c;为训练好一个高质量的检索模型&#xff0c;往往需要从大量的候选样本集合中采样高质量的负例&#xff0c;配合正例一起进行训练。 二、负难样本构建方法篇 …

WIFI-TTL透传模块说明书

WIFI-TTL透传模块说明书 V 1.0 2022-11-24 目录 1 简介... 4 2 模块参数... 4 3 接口定义... 5 4 设备配网... 6 5 AT指令... 11 6 恢复出厂... 12 7 设备配置... 13 7.1 配置界面说明... 13 7.2 TTL串口配置... 13 7.3 …

【Patroni官方文档】FAQ

FAQ&#xff08;常见问题解答&#xff09; 在本节中&#xff0c;您将找到关于Patroni的最常见问题的答案。每个小节都试图关注不同类型的问题。 我们希望这能帮助您澄清大部分问题。如果您仍然有进一步的疑虑或遇到意外问题&#xff0c;请参考“聊天和报告错误”部分&#xf…

交易术语汇总(Technical Trading Dictionary)

Arbitrage (套利) --- 一种利用交易所之间的差价获利的方法。 Accumulation (累积) --- 在一种资产中建立头寸的过程。 Ask/Bid (询价/竞价) --- 卖出订单是询价(Ask)&#xff0c;买入订单是出价(Bid)。 ATH&#xff08;历史最高价) --- All-time high 全时高。 Bearish MS…