【Java集合框架】3 - 5 LinkedList 源码分析

§3-5 LinkedList 源码分析

3-5.1 LinkedList 集合

LinkedListList 的一个实现类,本质上是一个双向链表,查询慢,增删快,首尾元素操作也是极快的。

所有的运算操作都基于双向链表进行,遍历时会从头结点或尾结点中最近的一个开始遍历。

该类并不同步,因此在多线程中访问同一个 LinkedList 实例,且至少有一个线程结构性地修改了该列表,则必须在外部同步。

由于 LinkedList 实现了 List 接口,因此,List 以及 Collection 中的方法都可用。但该类本身还提供了很多直接操作首尾结点的特有方法。

特有方法

方法 描述
void addFist(E e) 在该列表开头插入指定的元素
void addLast(E e) 在该列表末尾追加指定的元素
E getFirst(E e) 返回该列表的首元素
E getLast(E e) 返回该列表的末元素
E removeFirst(E e) 删除并返回该列表中的第一个元素
E removeLast(E e) 删除并返回该列表中的最后一个元素

注意

  • add 方法和 addLast 方法的效果相同;
  • 一般而言,使用其接口中的方法可以满足基本需求,上述的方法了解即可;

3-5.2 LinkedList 源码解析

LinkedList 的底层原理

  • LinkedList 中定义了一个内部类 Node<E>,表示结点;

    该内部类的声明为:

    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;
    
        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
    

    其中,item 用于存储数据项,nextprev 分别用于指向后继结点和前驱结点;

  • LinkedList 类中,定义了三个重要的成员变量 size, firstlast

    transient int size = 0;
    
    transient Node<E> first;
    
    transient Node<E> last;
    

    这三者分别用于表示链表长度、链表头节点和尾结点;

    LinkedList 的无参构造器实现为:

    public LinkedList() {
    }
    

    该构造体具有空实现,创建集合对象后,上述的三个变量具有默认初始值;

  • 调用 add 往该双向链表中添加元素;

    add 方法实现:

    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    

    在底层调用了另外一个方法 linkLast 添加元素,其实现为:

    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
    

    首先使用第三方变量添加元素前,链表的原始尾结点;

    该原始尾结点就是新结点的前驱结点,新结点此时将作为链表的尾结点,不存在后继节点;

    新结点创建完毕后,将链表的尾结点指针指向新结点;

    若为首次添加结点,则将链表的头结点指针指向该新结点;否则,将原尾结点的后继节点指针指向该新结点;

    元素添加完毕,更新链表长度和结构性修改次数;

posted @ 2023-08-05 17:24  Zebt  阅读(18)  评论(0)    收藏  举报