Java 集合框架分析:LinkedList

相关文章:
Java 集合框架分析:Set
http://blog.csdn.net/youyou1543724847/article/details/52733723
Java 集合框架分析:LinkedList
http://blog.csdn.net/youyou1543724847/article/details/52734935
Java 集合框架分析:DelayQueue
http://blog.csdn.net/youyou1543724847/article/details/52176504
Java 集合框架分析:ArrayBlockingQueue
http://blog.csdn.net/youyou1543724847/article/details/52174308
Java 集合框架分析:ArrayDeque
http://blog.csdn.net/youyou1543724847/article/details/52170026
Java 集合框架分析:PriorityBlockingQueue
http://blog.csdn.net/youyou1543724847/article/details/52166985
Java 集合框架分析:JAVA Queue源码分析
http://blog.csdn.net/youyou1543724847/article/details/52164895
Java 集合框架分析:关于Set,Map集合中元素判等的方式
http://blog.csdn.net/youyou1543724847/article/details/52733766
Java 集合框架分析:ConcurrentModificationException
http://blog.csdn.net/youyou1543724847/article/details/52733780
Java 集合框架分析:线程安全的集合
http://blog.csdn.net/youyou1543724847/article/details/52734876
Java 集合框架分析:JAVA集合中的一些边边角角的知识
http://blog.csdn.net/youyou1543724847/article/details/52734918

LinkedList的基本结构:

public class LinkedList<E>
    extends AbstractSequentialList
    implements List, Deque, Cloneable, java.io.Serializable
{
    transient int size = 0;//size存储了节点的个数,size()的复杂度为o(1)

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node first;

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node last;

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
    }

java.util.LinkedList是双向链表,这个大家都知道,比如Java的基础面试题喜欢问ArrayList和LinkedList的区别,在什么场景下用。大家都会说LinkedList随机增删多的场景比较合适,而ArrayList的随机访问多的场景比较合适。更进一步,我有时候会问,LinkedList.remove(Object)方法的时间复杂度是什么?有的人回答对了,有的人回答错了。回答错的应该是没有读过源码。

理论上说,双向链表的删除的时间复杂度是O(1),你只需要将要删除的节点的前节点和后节点相连,然后将要删除的节点的前节点和后节点置为null即可,

这个操作的时间复杂度可以认为是O(1)级别的。但是LinkedList的实现是一个通用的数据结构,因此没有暴露内部的节点Entry对象,remove(Object)传入的Object其实是节点存储的value,这里还需要一个查找过程:
Java 集合框架分析:LinkedList_第1张图片
因此,显然,LinkedList.remove(Object)方法的时间复杂度是O(n)+O(1),结果仍然是O(n)的时间复杂度,而非推测的O(1)复杂度。最坏情况下要删除的元素是最后一个,你都要比较N-1次才能找到要删除的元素。

总结下,LinkedList的两个remove方法,remove(Object)和remove(int)的时间复杂度都是O(n),在链表元素很多并且没有索引可用的情况下,LinkedList也并不适合做随机增删元素。在对性能特别敏感的场景下,还是需要自己实现专用的双向链表结构,真正实现 O(1)级别的随机增删。更进一步,jdk5引入的ConcurrentLinkedQueue是一个非阻塞的线程安全的双向队列实现,同样有本文提到的问题,有兴趣可以测试一下在大量元素情况下的并发随机增删,效率跟自己实现的特定类型的线程安全的链表差距是惊人的。

题外,ArrayList比LinkedList更不适合随机增删的原因是多了一个数组移动的动作,假设你删除的元素在m,那么除了要查找m次之外,还需要往前移动n-m-1个元素。

你可能感兴趣的:(JAVA,Java,编程,JAVA-集合)