百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

为什么我不推荐研发人员使用 LinkedList?

wxin55 2025-05-11 02:02 2 浏览 0 评论

在 Java 集合框架中,LinkedList 作为 List 的实现之一,经常被认为是 ArrayList 的替代方案。然而,在大多数实际场景下,我们并不推荐使用 LinkedList,原因主要集中在其性能劣势和使用上的局限性。

1. LinkedList的结构特性

LinkedList 本质上是一个双向链表,每个节点都存储着数据以及指向前后节点的引用。这种设计虽然在某些场景(如频繁的插入、删除操作)下有一定优势,但在大多数情况下却带来了更大的性能开销。

2. LinkedList的性能问题

(1) 各操作的时间复杂度

操作

时间复杂度

解释

复杂度来源

提升方案

add(E e)

O(1)

追加元素到链表尾部,直接修改尾指针

直接操作尾指针

无需优化

add(int index, E e)

O(n)

需要遍历找到插入位置,再修改指针

需要遍历 index 次

使用 ArrayList 或 ArrayDeque

remove(int index)

O(n)

需要先找到索引位置,再删除节点

需要遍历 index 次

使用 ArrayList 或 ArrayDeque

remove(Object o)

O(n)

需要遍历找到匹配的元素,再删除

需要查找元素

使用 HashMap 维护索引加速查找

get(int index)

O(n)

需要从头或尾部遍历到指定索引

需要遍历 index 次

使用 ArrayList

set(int index, E e)

O(n)

需要先找到索引位置,再修改值

需要遍历 index 次

使用 ArrayList

contains(Object o)

O(n)

需要遍历查找是否存在

需要查找元素

使用 HashSet 进行快速查找

size()

O(1)

直接返回存储的大小

直接返回计数

无需优化

iterator.remove()

O(1)

通过迭代器删除元素,避免遍历

直接修改指针

无需优化

removeFirst() / removeLast()

O(1)

直接修改头尾指针

直接操作头/尾

无需优化

(2) 随机访问性能差

ArrayList 通过数组下标访问元素的时间复杂度是 O(1),而 LinkedList 需要从头或尾部开始遍历,平均时间复杂度为 O(n)。当列表较大时,频繁的 get(index) 操作会极大影响性能。

List<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 100000; i++) {
    linkedList.add(i);
}

long start = System.nanoTime();
linkedList.get(50000); // O(n)
long end = System.nanoTime();
System.out.println("LinkedList get operation time: " + (end - start) + " ns");

(3) 额外的内存开销

相比 ArrayList 仅存储数据本身,LinkedList 还需要额外的指针存储前后节点的引用。对于每个元素,LinkedList 需要额外占用 2 倍的指针空间,这在大规模数据存储时会带来额外的内存开销

(4) 插入和删除操作并不总是快

如果删除的是头部或尾部元素,LinkedList 的表现确实优于 ArrayList,因为它的 removeFirst() 和 removeLast() 仅需 O(1)。但对于中间元素,LinkedList 需要先遍历找到节点,然后再执行删除,整体仍是 O(n),并不比 ArrayList 更快。

3. 自己实现一个 LinkedList

如果想要更通用的 LinkedList,可以自己实现一个双向链表,优化其遍历性能:

class MyLinkedList<T> {
    private static class Node<T> {
        T data;
        Node<T> prev, next;
        Node(T data) { this.data = data; }
    }

    private Node<T> head, tail;
    private int size;

    public void add(T data) {
        Node<T> newNode = new Node<>(data);
        if (tail == null) {
            head = tail = newNode;
        } else {
            tail.next = newNode;
            newNode.prev = tail;
            tail = newNode;
        }
        size++;
    }

    public void remove(T data) {
        Node<T> current = head;
        while (current != null) {
            if (current.data.equals(data)) {
                if (current.prev != null) current.prev.next = current.next;
                if (current.next != null) current.next.prev = current.prev;
                if (current == head) head = current.next;
                if (current == tail) tail = current.prev;
                size--;
                return;
            }
            current = current.next;
        }
    }

    public int size() { return size; }
}

4. 替代方案

在大多数情况下,ArrayList 由于其更快的访问速度、更少的内存占用和更好的 CPU 缓存友好性,是更优的选择。如果需要高效的插入和删除操作,并且对内存占用敏感,可以考虑 ArrayDeque 或 ConcurrentLinkedQueue。

5. 结论

除非有非常明确的需求,否则在 Java 开发中不建议使用 LinkedList 作为默认的 List 实现。ArrayList 在大多数场景下更高效,而 Deque(如 ArrayDeque)则能更好地替代 LinkedList 作为队列使用。理解这些数据结构的特性,有助于我们在开发中做出更好的选择,避免性能陷阱。

你在项目中是否有过使用 LinkedList 的经验?在你的使用场景中,它的表现如何?你是否也曾遇到性能瓶颈?欢迎在评论区分享你的看法与经验,我们一起来讨论如何在不同场景下选择最合适的数据结构!

相关推荐

Java中List 和 Map、Set 的区别(list和set和map)

hello,大家好,我是霖仔java集合的大家了解,我再给大家说一下他们的区别,希望能够帮助到大家结构特点:List和Set是存储单列数据的集合,Map是存储键和值这样的双列数据的集合;Lis...

Java 集合框架全面解析:选对数据结构,提升开发效率

上一章我们详细介绍了各种常用的数据结构情况(参考:数据结构复杂度全览:如何选择最优结构?),本文结合关键数据结构,从列表(List)、队列(Queue)、集合(Set)、映射(Map)四个维度,深入解...

LinkedList竟然比ArrayList慢了1000多倍?(动图+性能评测)

数组和链表是程序中常用的两种数据结构,也是面试中常考的面试题之一。然而对于很多人来说,只是模糊的记得二者的区别,可能还记得不一定对,并且每次到了面试的时候,都得把这些的概念拿出来背一遍才行,未免有些麻...

LinkedList 底层源码深度解析(linkedlist底层数据结构)

目录1.引言2.LinkedList概述2.1类继承体系图2.2各个接口作用3.与ArrayList的对比4.底层数据结构5.核心方法源码解析5.1add()方法5.2a...

List的用法和实例详解——Java进阶知识讲义系列(四)

序欢迎来到全网最完整的Java进阶知识系列教程!!!每天定时更新!!!本期是Java进阶知识系列的第四讲,将分享Java常用的数据容器——集合类。集合类也分很多类型,比如:List、Set、Map、Q...

Rust高效集合操作(rust基本操作)

集合的分类Rust的集合类型主要分布在标准库的std::collections模块中,同时也包括语言内置的数组和字符串类型序列容器序列容器维护元素的顺序,适合需要按索引访问或顺序遍历的场景向量(...

Java八股文:核心知识点梳理(java八股文是啥)

一、Java基础1.Java基本数据类型8种基本类型:整型:byte(1),short(2),int(4),long(8)浮点型:float(4),double(8)字符型:char(2)布...

面试题:ArrayList和LinkedList有什么区别?

面试题

为什么我不推荐研发人员使用 LinkedList?

在Java集合框架中,LinkedList作为List的实现之一,经常被认为是ArrayList的替代方案。然而,在大多数实际场景下,我们并不推荐使用LinkedList,原因主要集中...

ArrayList 、 LinkedList、Vector的区别

ArrayList、LinkedList、Vector的区别如下:ArrayListLinkedListVector结构动态数组双向链表动态数组是否线程安全否否是效率遍历查找快,插入删除慢插入删除...

(2020 )Java最新面试笔试题答案解析(一)

Java中的集中基本数据类型是什么?各占用多少字节?【数值型】—(整数类型)byte(1字节)short(2字节)int(4字节)long(8字节)拓展:Java中的数据类型除了上面的基本...

超简单五步实现Linux虚拟机CentOS 7系统Root密码忘记重置

环境:CentOS7.5重置root密码:1.CentOS7虚拟机开机,将鼠标光标移动至虚拟机内。2.在虚拟机中使用键盘上↑和↓键将选择行设置为第一行(背景高亮即为选中),按下键盘上的e,进...

吊轨门和推拉门哪个好?北京今朝区别介绍看完不入坑

厨房到底使用什么门好?相信这是大多数业主都比较抓狂的事情,其实在装修中材料的选择最终还是要依据空间而定,那么吊轨门和推拉门哪个好呢?下面就跟随北京装修网一起来看看吧!吊轨门与推拉门介绍吊轨门吊轨门的特...

〖省钱宝典〗不花冤枉钱,少走弯路!居家中推拉门如何设计?

想要空间最大程度的显大?想要充足的光线?又想拥有合理的区域划分?那么推拉门是你绝对不能错过的好选择。推拉门的设计轻盈简洁,绝对是室内每个空间的福音。它不仅可以最大化地节省空间,方便了居室的功能划分和利...

吊趟门与推拉门有什么区别?(吊趟门贵还是推拉门贵)

吊趟门与推拉门的区别很多人在购买的时候并不清楚,有些客人甚至根本分不清吊趟门和推拉门,今天小编就给大家讲讲吊趟门与推拉门的相关内容,看看吊趟门与推拉门的区别有哪些?1、推拉门采用以门扇下滑轮为主支撑点...

取消回复欢迎 发表评论: