当前位置: 首页 > 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.xdnf.cn/news/1360279.html

相关文章:

  • 【Protues仿真】基于AT89C52单片机的温湿度测量
  • 【文献阅读】生态恢复项目对生态系统稳定性的影响
  • 在JavaScript中,比较两个数组是否有相同元素(交集)的常用方法
  • 解决编译osgEarth中winsocket2.h找不到头文件问题
  • Node.js自研ORM框架深度解析与实践
  • C++11新特性全面解析(万字详解)
  • Starlink第三代终端和第二代终端的差异性有哪些?
  • Flink SQL执行SQL错误排查
  • MySQL的安装和卸载指南(入门到入土)
  • ZKmall模块商城的推荐数据体系:从多维度采集到高效存储的实践
  • 从“小麻烦”到“大难题”:Spring Boot 配置文件的坑与解
  • 04-ArkTS编程语言入门
  • 使用UE5开发《红色警戒3》类战略养成游戏的硬件配置指南
  • 源码导航页
  • Linux网络启程
  • 毛选一卷解析
  • 时间复杂度
  • C++STL底层原理:探秘标准模板库的内部机制
  • 大数据毕业设计选题推荐:基于Spark+Django的学生创业数据分析可视化系统详解 毕业设计/选题推荐/深度学习/数据分析/数据挖掘/机器学习/随机森林
  • Go语言IDE安装与配置(VSCode)
  • wpf之DockPanel
  • Python 闭包详解
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(十三)菜单、右键菜单
  • JDK版本报错
  • Function + 枚举 + Map:轻量路由器的最佳实践
  • [GeographicLib] LocalCartesian用法
  • 时序数据库选型“下半场”:从性能竞赛到生态博弈,四大主流架构深度横评
  • Palantir Foundry 领先其他数据平台5到10年:一位使用者的深入观察
  • 门面设计模式
  • 第4章 SPSS简介与数据库构建