数据结构-LinkedList原理

1. 简介

1.1 同 ArrayList 区别是什么?

  • ArrayList
    • 优点:底层是数组,检索非常快
    • 缺点:底层是数组,所以扩容需要申请新的数组并且要把老数据拷贝到新数组,代价比较大
  • LinkedList
    • 优点:进行增删改仅需要改变两个节点的指针引用即可,较快
    • 缺点:底层是链表,通过下标寻找元素,需要从链表头开始一个节点一个节点往下寻找,检索比较慢

1.2 继承关系

相较于 ArrayList ,LinkedList 多实现了接口 Queue (队列)、Deque (双端队列)。

队列的含义是先进先出,双端队列顾名思义就是可以把队列的首尾都当作队列处理,也就是首尾都可以增删元素,说明 LinkedList 除了队列先进先出的能力还具有栈先进后出的能力。

2. LinkedList 方法

2.1 构造方法

构造器 描述
LinkedList() 构造一个空列表。
LinkedList​(Collection<? extends E> c) 按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。

2.2 具体方法

变量和类型 方法 方法来源 操作 位置 列表内为空处理
void add​(int index, E element) List 增 指定位置
boolean add​(E e) Queue 增 末尾
void addFirst​(E e) Deque 增 开头
void addLast​(E e) Deque 增 末尾
void clear() Collection 删 所有位置
Iterator<E> descendingIterator() Deque 迭代
E element() Queue 检索 开头
E get​(int index) List 检索 指定位置
E getFirst() Deque 检索 开头
E getLast() Deque 检索 末尾
boolean offer​(E e) Queue 增 末尾
boolean offerFirst​(E e) Deque 增 开头
boolean offerLast​(E e) Deque 增 末尾
E peek() Queue 检索 开头
E peekFirst() Deque 检索 开头
E peekLast() Deque 检索 末尾
E poll() Queue 检索,删 开头 返回 null
E pollFirst() Deque 检索,删 开头 返回 null
E pollLast() Deque 检索,删 末尾 返回 null
E pop() Deque 检索,删 开头 异常
void push​(E e) Deque 增 末尾
E remove() Queue 检索 开头 异常
E remove​(int index) List 检索,删 指定位置 异常
boolean remove​(Object o) List 检索,删 第一个匹配项 异常
E removeFirst() Deque 检索,删 开头 异常
boolean removeFirstOccurrence​(Object o) Deque 删 第一个匹配项 异常
E removeLast() Deque 检索,删 末尾 异常
boolean removeLastOccurrence​(Object o) Deque 删 最后一个匹配项 异常
E set​(int index, E element) List 设置 指定位置

2.3 重点方法原理讲解

add​(int index, E element)

LinkedList 中的每一个节点都有两个指针 next(指向下一个节点),prev(指向上一个节点)。 如上图,如果想要用 NEW 2 把 2 替代,需要做的工作如下:

  • 将 2 的 next 指针与 prev 指针指向 null,此时 2 便不会被引用,也不会引用其他节点
  • 将 NEW 2 的 next 指针指向 3,prev 指针指向 1
  • 将 1 的 next 指针指向 NEW 2
  • 将 3 的 prev 指针指向 NEW 2
  • 注意,如果替换的节点是 Head 节点/ Tail 节点,还需要改变两个指针的指向引用

remove​(int index)

如上图,如果需要删除一个节点,需要做的工作如下:

  • 将 2 的 next 指针与 prev 指针指向 null,此时 2 便不会被引用,也不会引用其他节点
  • 将 1 的 next 指针指向 3
  • 将 3 的 prev 指针指向 1
  • 注意,如果删除的节点是 Head 节点/ Tail 节点,还需要改变两个指针的指向引用

3. 总结

对于查操作较多的场景用 ArrayList 性能更好,可以直接获取到内存中的地址,不用遍历。

对于增删操作多的场景用 LinkedList ,只需要改变指针指向即可,不需要进行扩容拷贝。

LinkedList 具有队列和栈的能力,有相关需求在使用时可以考虑这两个特性。

小贴士:可以用 LinkedList 的队列特性对树结构进行广度优先搜索

java 复制代码
class TreeNode {
    private int val;
    private TreeNode left;
    private TreeNode right;
}

public static void main(String[] args) {
    TreeNode root;

    LinkedList<TreeNode> queue = new LinkedList<>();
    queue.add(root);

    while (!queue.isEmpty()) {
        for (int i = queue.size() - 1 /*拷贝队列当前元素数量*/; i >= 0; i--) {
            TreeNode treeNode = queue.poll();
            TreeNode left = treeNode.left;
            TreeNode right = treeNode.right;

            System.out.println(treeNode.val);

            if (left != null) {
                queue.offer(left);
            }
            if (right != null) {
                queue.offer(right);
            }
        }
    }
}
相关推荐
Mikko710 分钟前
用 Java 复刻了高中时在塞班上玩的「熔岩矿车」:纯 Swing、零依赖、没有一张图片,一个 jar 双击就能玩
java·游戏开发·swing
知了学历孙老师12 分钟前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
Java爱好狂.31 分钟前
Java初学者如何一周速通SpringBoot!
java·spring boot·后端·spring·高并发·架构师·java面试
秋饼1 小时前
LLM API密钥动态轮换实战:Spring Vault + Spring AI + 多Provider路由
java·ai·技术分享·后端开发
马良神笔2 小时前
2026 年Rag最近技术前沿总结
后端·python·django
程序猿DD2 小时前
同样10美元,OpenDesign和Command Code的DeepSeek V4.1 Flash额度到底有多少?
后端
福兮说3 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
高频因子挖掘机3 小时前
A股量化从日线升级到5分钟线:数据量增加后最先暴露哪些工程问题?
后端·github·api
高频因子挖掘机3 小时前
历史行情返回顺序变了,为什么按行号计算指标很危险?
后端·github·api
紧跟先前的步伐4 小时前
Go AI Agent 实战 03|Token、上下文窗口与模型调用成本
java·人工智能·golang