一文详解Java17中LinkedList类的用法和应用场景
作者:小猿、
概述
LinkedList 是 Java 集合框架中基于双向链表实现的类,实现了 List 和 Deque 接口。在 Java 17 中,其核心实现与旧版本保持一致,但在现代 Java 编程中可以结合新特性(如 var、Stream API)更高效地使用。
一、核心特性(Java 17 视角)
双向链表结构:每个节点包含数据、前驱和后继节点的引用,与旧版本一致。
高效增删操作:头尾插入/删除时间复杂度为 O(1),中间插入需遍历链表(O(n))。
低效随机访问:按索引访问需遍历链表(O(n)),性能低于 ArrayList。
多接口支持:可作为列表、队列(Queue)、双端队列(Deque)或栈(Stack)使用。
非线程安全:需手动同步或使用 Collections.synchronizedList() 包装。
兼容性:完全支持 Java 17 的模块化系统(JPMS),无缝集成现代 Java 项目。
二、应用场景
频繁增删数据:如动态维护任务列表、事件队列。
实现队列/栈:利用 offer()/poll()(队列)或 push()/pop()(栈)方法。
操作头尾元素:例如实现 LRU 缓存、撤销操作(Undo/Redo)。
无需预分配内存:链表动态扩展,避免数组复制的开销。
结合 Stream API:通过链式操作处理数据(如过滤、映射)。
三、Java 17 中的代码示例
1. 创建 LinkedList 并操作元素(使用 var 关键字)
import java.util.LinkedList; public class LinkedListDemo { public static void main(String[] args) { var list = new LinkedList<String>(); // 类型推断(Java 10+) // 添加元素(支持链式调用) list.add("A") .addFirst("B") .addLast("C") .add(1, "D"); System.out.println("初始化后: " + list); // 输出: [B, D, A, C] // 删除元素(结合 Lambda 表达式) list.removeIf(s -> s.equals("A")); // 删除 "A" System.out.println("删除后: " + list); // 输出: [B, D, C] } }
2. 作为双端队列(Deque)使用
var deque = new LinkedList<Integer>(); // 头部插入 deque.offerFirst(10); // 尾部插入 deque.offerLast(20); // 头部删除 System.out.println(deque.pollFirst()); // 输出: 10 // 尾部删除 System.out.println(deque.pollLast()); // 输出: 20
3. 结合 Stream API 处理数据
var numbers = new LinkedList<>(List.of(1, 2, 3, 4, 5)); // 过滤偶数并转换为字符串 List<String> result = numbers.stream() .filter(n -> n % 2 == 0) .map(Object::toString) .toList(); System.out.println(result); // 输出: [2, 4]
4. 实现 LRU 缓存(最近最少使用)
public class LRUCache<K, V> { private final LinkedList<K> accessOrder = new LinkedList<>(); private final Map<K, V> cache = new HashMap<>(); private final int capacity; public LRUCache(int capacity) { this.capacity = capacity; } public V get(K key) { if (cache.containsKey(key)) { accessOrder.remove(key); // 移除旧位置 accessOrder.addFirst(key); // 更新为最近访问 return cache.get(key); } return null; } public void put(K key, V value) { if (cache.size() >= capacity) { K oldest = accessOrder.removeLast(); // 删除最久未使用的键 cache.remove(oldest); } accessOrder.addFirst(key); cache.put(key, value); } }
四、与 ArrayList 的对比(Java 17 优化建议)
场景 | LinkedList 适用性 | ArrayList 适用性 |
---|---|---|
频繁增删 | ✅ 头尾操作高效,中间操作需遍历 | ❌ 中间插入/删除需移动元素 |
随机访问 | ❌ 遍历链表(O(n)) | ✅ 直接索引访问(O(1)) |
内存占用 | ❌ 存储节点指针占用更多内存 | ✅ 连续内存,空间局部性更优 |
Java 17 新特性 | ✅ 结合 Stream API 和 var 简化代码 | ✅ 同样适用 |
五、Java 17 中的注意事项
1、避免索引遍历:优先使用迭代器或 forEach 方法:
list.forEach(System.out::println); // 推荐方式
2、空值处理:允许存储 null,但需注意空指针异常。
3、线程安全:多线程环境下使用同步包装类:
var syncList = Collections.synchronizedList(new LinkedList<>());
4、内存敏感场景:链表节点占用更多内存,需谨慎用于大规模数据。
5、模式匹配:可结合 Java 17 的 switch 模式匹配处理链表元素:
Object element = list.getFirst(); switch (element) { case String s -> System.out.println("String: " + s); case Integer i -> System.out.println("Integer: " + i); default -> System.out.println("Unknown type"); }
六、总结
在 Java 17 中,LinkedList 仍然是处理频繁增删和双端操作的理想选择,尤其适合队列、栈、缓存等场景。结合现代 Java 特性(如 var、Stream API)可以提升代码简洁性和可读性。若需快速随机访问或内存敏感,优先选择 ArrayList。根据需求选择数据结构,是高效开发的关键!
到此这篇关于一文详解Java17中LinkedList类的用法和应用场景的文章就介绍到这了,更多相关Java17 LinkedList类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!