双向链表结构

LinkedList作为java又一大常用集合,其内部也有许多特性需要关注,首先我们从源码可以剖析出LinkedList为一个双向链表结构,如下图:
linkedlist.png

具体源码分析如下:

首先是LinkedList里的重要属性:

    //链表首指针
    transient Node<E> first;
    //链表尾指针
    transient Node<E> last;

LinkedList的默认构造器为一个空构造器:

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

下面来看看linkedlist的add方法:

     public boolean add(E e) {
        linkLast(e);
        return true;
    }
    
    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++;
    }
    
    //Node为LinkdList的静态内部类
    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;
        }
    }

可以看出整个数据结构是以双向链表操作添加节点的。

linkedList中还有一个重要的get方法,通过双向链表的特殊特性遍历节点时无需遍历全部节点即可找出所需节点:

 public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }

关注node方法里的算法:

    Node<E> node(int index) {
        // assert isElementIndex(index);
           
        //判断传入的索引位置是否靠近最左端还是最右端
        if (index < (size >> 1)) {
            //靠近左端则用首指针遍历
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            //靠近右端则用尾指针遍历
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

艾尔雪枫
25 声望5 粉丝

Change every day!