当前位置: 首页 > news >正文

Java:LinkedList的使用

目录

一、概念

二、常用操作

2.1 基于List的操作

2.2 队列(Queue)、栈(Stack)和双端队列(Deque)操作

2.3 遍历


一、概念

LinkedList 在 Java 中是一个基于双向链表实现的 List 接口的实现类。它同时实现了 List 和 Deque(双端队列)接口,所以它同时具备了列表和队列的特性。

核心特点:

  • 非连续存储:元素分散存储在堆内存中,通过引用相连。这使其在内存利用上更灵活,但每个元素需要额外的空间来存储前后节点的引用(内存开销更大)。

  • 动态大小:与数组不同,链表的大小是动态的,可以自由地添加和删除元素,无需担心容量问题。

  • 插入和删除高效在已知位置(通过迭代器定位)进行插入和删除操作的时间复杂度是 O(1)。这是它相对于 ArrayList 最大的优势。因为它只需要修改相邻节点的引用即可,而不需要像数组那样移动大量元素。

  • 随机访问低效根据索引访问元素(get(i)set(i, element))的时间复杂度是 O(n)。因为它必须从链表的头部(或尾部,JDK 做了优化)开始遍历,直到找到第 i 个节点。

  • 实现了双端队列(Deque):提供了丰富的方法,如 addFirst()addLast()removeFirst()removeLast()getFirst()getLast() 等,可以非常方便地将其用作栈(Stack)、队列(Queue)或双端队列(Deque)。

二、常用操作

2.1 基于List的操作

LinkedList<String> list = new LinkedList<>();// 添加元素
list.add("Apple");        // 添加到尾部
list.add(1, "Banana");   // 在指定索引位置插入
list.addFirst("First");   // 添加到头部 (Deque 方法)
list.addLast("Last");     // 添加到尾部 (Deque 方法,等同于 add())// 获取元素
String first = list.get(0);     // 根据索引获取
String head = list.getFirst();  // 获取头部元素
String tail = list.getLast();   // 获取尾部元素// 删除元素
list.remove(1);           // 根据索引删除
list.remove("Apple");     // 根据元素内容删除(首次出现)
list.removeFirst();       // 删除并返回头部元素
list.removeLast();        // 删除并返回尾部元素// 检查大小和内容
int size = list.size();
boolean isEmpty = list.isEmpty();
boolean hasApple = list.contains("Apple");// 替换元素
list.set(0, "New First"); // 将索引0位置的元素替换

2.2 队列(Queue)、栈(Stack)和双端队列(Deque)操作

LinkedList<String> queue = new LinkedList<>();// 作为普通队列 (FIFO: First-In-First-Out)
queue.offer("A"); // 入队(添加到尾部),推荐使用
queue.add("B");   // 入队(添加到尾部),失败会抛异常
String s1 = queue.poll(); // 出队(移除并返回头部元素),队列空则返回null
String s2 = queue.remove(); // 出队,队列空则抛异常 NoSuchElementException
String s3 = queue.peek(); // 获取但不移除头部元素,空则返回null
String s4 = queue.element(); // 获取但不移除头部元素,空则抛异常// 作为栈 (LIFO: Last-In-First-Out)
LinkedList<String> stack = new LinkedList<>();
stack.push("A"); // 压栈(添加到头部)
stack.push("B");
String top = stack.pop(); // 出栈(移除并返回头部元素)
String top2 = stack.peek(); // 查看栈顶元素// 作为双端队列 (Deque)
queue.offerFirst("A"); // 添加到头部
queue.offerLast("Z");  // 添加到尾部(等同于 offer)
String first = queue.pollFirst(); // 从头部移除
String last = queue.pollLast();   // 从尾部移除

典型使用场景:

  • 实现栈(LIFO)addFirst() / removeFirst()

  • 实现队列(FIFO)offer() / poll() 或 addLast() / removeFirst()

  • 实现双端队列:各种 First/Last 方法

操作方法示例时间复杂度说明
头部插入addFirst(e)offerFirst(e)O(1)
尾部插入add(e)addLast(e)offer(e)offerLast(e)O(1)
指定位置插入add(index, e)O(n)主要耗时在遍历到 index 位置
头部删除removeFirst()pollFirst()O(1)
尾部删除removeLast()pollLast()O(1)
指定元素/位置删除remove(o)remove(index)O(n)主要耗时在遍历找到元素或位置
随机访问(获取)get(index)O(n)需要遍历
随机访问(修改)set(index, e)O(n)需要遍历到位置后再修改,修改本身是 O(1)
查找元素位置indexOf(o)O(n)需要遍历比较
检查是否包含contains(o)O(n)内部调用 indexOf

队列使用示例:

import java.util.LinkedList;
import java.util.Queue;public class QueueExample {public static void main(String[] args) {Queue<Integer> queue = new LinkedList<>();// 生产者:入队10个任务for (int i = 0; i < 10; i++) {queue.offer(i);System.out.println("任务入队: " + i);}// 消费者:处理所有任务while (!queue.isEmpty()) {Integer task = queue.poll();System.out.println("处理任务: " + task);}}
}

2.3 遍历

千万不要用 for-i 循环(基于索引的循环)来遍历 LinkedList
因为每次 get(i) 都会从链表头开始遍历,会导致时间复杂度变为 O(n²),性能极差。

// foreach 循环(推荐):语法简洁,底层使用迭代器,效率高。
for (String item : list) {System.out.println(item);
}// 迭代器(Iterator):更灵活,可以在遍历时使用 iterator.remove() 安全地删除元素。
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {String item = iterator.next();if ("某些条件") {iterator.remove(); // 安全删除!}
}// ListIterator:功能更强大的迭代器,可以双向遍历(向前/向后)以及在遍历时添加和修改元素。
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {String next = listIterator.next();listIterator.set("Modified: " + next); // 修改元素listIterator.add("Added"); // 添加元素
}

http://www.dtcms.com/a/348056.html

相关文章:

  • Django的Settings 配置文件详解
  • 【ArcGIS Pro 全攻略】GIS 数据格式终极指南:从原理到实战,再也不纠结选哪种格式!
  • React useState 全面深入解析
  • Linux 824 shell:expect
  • 基于5G NR NTN与DVB-S2X/RCS2的机载卫星通信终端性能分析
  • 低功耗模式DMA数据搬运问题解析
  • 在测试接入抖音小游戏订阅消息推送时遇到的问题
  • bun + vite7 的结合,孕育的 Robot Admin 【靓仔出道】(十八)
  • K8s部署MySQL8.0数据库
  • Transformer实战(13)——从零开始训练GPT-2语言模型
  • 【go语言】字符串函数
  • imx6ull-驱动开发篇39——Linux INPUT 子系统实验
  • 05-ArkUI界面开发
  • Solidity学习笔记
  • ZKmall模块商城的推荐数据体系:从多维度采集到高效存储的实践
  • 用 Bright Data MCP Server 构建实时数据驱动的 AI 情报系统:从市场调研到技术追踪的自动化实战
  • 青少年软件编程(python五级)等级考试试卷-客观题(2024年6月)
  • 数据库原理及应用_数据库基础_第2章关系数据库标准语言SQL_数据的维护
  • Adobe CS6所有系列绿色免安装版,Photoshop 6 Adobe Illustrator CS6 等绿色版
  • Spring创建的方式
  • 使用 Frida 运行时检测 Android 应用的真实权限状态 (App Ops)
  • 第4章栈和队列:顺序队——基本结构
  • Java 基础学习总结(211)—— Apache Commons ValidationUtils:让参数校验从 “体力活“ 变 “优雅事“
  • Vue状态管理工具pinia的使用以及Vue组件通讯
  • 一个byte表示多个bool属性的功能
  • 高并发AI服务部署方案:vLLM、TGI、FastChat性能压测报告
  • CSS 进阶用法
  • Read View是实现MVCC的三大前提之一,那么它是在什么时候建立的
  • frida安装配置及其使用方法
  • 一个奇怪的问题-Python会替代Java吗?技术语言之争的真相-优雅草卓伊凡