详细的LinkedList...

1,204 阅读13分钟

LinkedList底层是使用双向链表实现的,他实现了List接口和Deque接口(该接口继承自Queue接口),所以LinkedList可以被安全的转为Deque和Queue。实际上她现在也是使用Deque与Queue的推荐实现。LinkedList中可以存放任何引用类型的元素。包括null。

声明

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
	//代码
}

该类继承自AbstractSequentialList,这个可以标识LinkedList只能支持顺序访问,不能像ArrayList那样支持随机访问。

成员变量

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    //表示linkedList中存放的元素的数字
    transient int size = 0;

    /**
     * 用于定位首节点。
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * 用于定位尾节点。
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;
    
    //用于序列化
    private static final long serialVersionUID = 876323262645176354L;
}

LinkedList内部使用Node来作为链表节点存放我们放入其中的元素的。

存放元素的盒子——Node

Node节点是LinkedList实现双向链表的关键,它是在LinkedList内部以私有内部类的形式定义供LinkedList的API使用,Node的定义还是挺简单的,就是实现双向链表的最基本的元素节点。

    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;
        }
    }

构造方法——如何初始化

    /**
     * 无参数的构造方法,可以看到没有进行任何的动作。
     */
    public LinkedList() 
    {
    }

    /**
     * 将Collection实现类的实例c中的元素使用LinkedList的addAll方法添加到内部的双向链表中。
     */
    public LinkedList(Collection<? extends E> c) 
    {
        this();
        addAll(c);
    }

LinkedList提供两个构造方法来初始化。

常用方法

获取元素

getFirst方法

    /**
     * 该方法用于返回链表头指针所指向的结点的元素。如果链表为空,那么将抛出异常。
     */
    public E getFirst()
    {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

getLast方法

    /**
     * 该方法用于返回链表尾指针所指向的结点的元素。如果链表为空,那么将抛出异常。
     */
    public E getLast() 
    {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

get方法

    /**
     * 返回指定下标处的结点内部的item中存放的值,由于链表的特性,该方法的时间复杂度为O(n)。
     * 该方法内部通过node方法定位指定下标元素。该方法首先要检查下标是否合理。合理的范围是[0,size-1]
     * 如何不合理将抛出 IndexOutOfBoundsException异常。
     */
    public E get(int index) 
    {
        checkElementIndex(index);
        return node(index).item;
    }

    private void checkElementIndex(int index)
    {
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 修改或者获取元素是的下标检查。
     */
    private boolean isElementIndex(int index) 
    {
        return index >= 0 && index < size;
    }

peek方法

    /**
     * 返回链表的头指针指向的元素,如果链表为空返回null,但不删除。
     */
    public E peek() 
    {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }

peekFirst方法

    /**
     * 返回链表的头指针指向的元素,如果链表为空返回null,但不删除。该方法与peek方法实现完全一致。
     */
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
     }

peekLast方法

    /**
     * 返回链表的尾指针指向的元素,如果链表为空返回null,但不删除。
     */
    public E peekLast()
    {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }

element方法

    /**
     * 该方法与peek方法基本一致。该方法适用getFirst获取头指针指向的结点内的item值。
     * 不同的是,如果链表为空,该方法将抛出异常。
     */
    public E element() 
    {
        return getFirst();
    }

getFirst方法

    /**
     * 返回头指针指向的结点内的item值。如果链表为空,则抛出NoSuchElementException。
     */
    public E getFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

删除元素

remove方法

    /**
     * 从头结点开始寻找,判断节点内部的item是否与传入的0相等,或者为null(o为null)。
     * 如果找到,则使用unlink方法删除该节点,并返回true。
     * 如果没有找到,链表不做修改,返回false。
     */
    public boolean remove(Object o) 
    {
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next)
            {
                if (x.item == null)
                {
                    unlink(x);
                    return true;
                }
            }
        }
        else 
        {
            for (Node<E> x = first; x != null; x = x.next) 
            {
                if (o.equals(x.item)) 
                {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * 将节点x从链表中移除,要求x不能为空。
     */
    E unlink(Node<E> x)
    {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;

        if (prev == null) 
        {
            first = next;
        } 
        else
        {
            prev.next = next;
            x.prev = null;
        }

        if (next == null)
        {
            last = prev;
        }
        else 
        {
            next.prev = prev;
            x.next = null;
        }

        x.item = null;
        size--;
        modCount++;
        return element;
    }

    /**
     * 不带任何参数的remove方法将于removeFirst相同,删除链表的头指针所指向的元素。
     */
    public E remove()
    {
        return removeFirst();
    }

poll方法

    /**
     * 删除并返回头指针指向的元素。该方法内部使用unlinkFirst操作。只不过如何连表为空返回null
     */
    public E poll() 
    {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

pop方法

   /**
     * 弹出栈顶元素,也就是链表的首节点所指向的元素,如果链表为空那么将抛出异常。
     */
    public E pop() 
    {
        return removeFirst();
    }

removeFirst方法

	/**
     * 删除并返回链表头指针所指向的结点的元素,如果链表为空则抛出异常。该方法使用unlinkFirst方法删除头结点的元素。
     * 可以确保传入unlinkFirst的头结点不为空
     */
    public E removeFirst() 
    {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    /**
     * 将头指针指向的头结点从链表中移除。要求f必须不为null,并且f是当前链表的头结点。
     */
    private E unlinkFirst(Node<E> f) 
    {
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null;
        f.next = null; // help GC,这里不用设置prev因为,f为头结点,其prev本身为null
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

removeFirstOccurrence方法

    /**
     * 从头指针指向的结点开始向后遍历,找到第一个与o相等或者等于null(o为null)的元素,将其删除。如果删除成功返回true。
     * 如果没有周到返回false。
     */
    public boolean removeFirstOccurrence(Object o) 
    {
        return remove(o);
    }

removeLastOccurrence方法

 	/**
     * 从尾指针指向的结点开始向前遍历,找到第一个与o相等或者等于null(o为null)的元素,将其删除。如果删除成功返回true。
     * 如果没有周到返回false。
     */
    public boolean removeLastOccurrence(Object o) 
    {
        if (o == null) 
        {
            for (Node<E> x = last; x != null; x = x.prev) 
            {
                if (x.item == null) 
                {
                    unlink(x);
                    return true;
                }
            }
        }
        else 
        {
            for (Node<E> x = last; x != null; x = x.prev) 
            {
                if (o.equals(x.item)) 
                {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }

pollFirst方法

    /**
     * 删除并返回头指针指向的元素。该方法内部使用unlinkFirst操作。该方法与poll方法完全一致。
     */
    public E pollFirst() 
    {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

removeLast方法

	/**
     * 删除并返回链表尾指针所指向的结点的元素,如果链表为空则抛出异常。该方法使用unlinkLast方法删除尾结点的元素。
     * 可以确保传入unlinkLast的尾结点不为空
     */
    public E removeLast() 
    {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

    /**
     * 将尾指针指向的尾结点从链表中移除。要求f必须不为null,并且f是当前链表的尾结点。
     */
    private E unlinkLast(Node<E> l) 
    {
        // assert l == last && l != null;
        final E element = l.item;
        final Node<E> prev = l.prev;
        l.item = null;
        l.prev = null; // help GC 这里不用设置next因为,f为尾结点,其next本身为null
        last = prev;
        if (prev == null)
            first = null;
        else
            prev.next = null;
        size--;
        modCount++;
        return element;
    }

pollLast方法

    /**
     * 删除并返回链表尾指针指向的结点内的元素,如果链表为空,则返回null,这个与removeLast区分。
     */
    public E pollLast() 
    {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }

clear方法

    /**
     * 删除集合链表中的所有的元素,该方法执行完成后。链表将为空。
     * 最后还有置空头指针和尾指针。
     */
    public void clear() 
    {
        // Clearing all of the links between nodes is "unnecessary", but:
        // - helps a generational GC if the discarded nodes inhabit
        //   more than one generation
        // - is sure to free memory even if there is a reachable Iterator
        for (Node<E> x = first; x != null; ) 
        {
            Node<E> next = x.next;
            x.item = null;
            x.next = null;
            x.prev = null;
            x = next;
        }
        first = last = null;
        size = 0;
        modCount++;
    }

添加元素

add方法

    /**
     * 该方法将元素添加到链表的尾部,该方法与addLast逻辑完全一致,只不过该方法会返回true.
     */
    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++;
    }

offer方法

    /**
     * 添加元素e到链表的尾部。该方法与add方法作用一致。
     */
    public boolean offer(E e) 
    {
        return add(e);
    }

push方法

    /**
     * 将元素e加入到链表的头部。
     */
    public void push(E e) 
    {
        addFirst(e);
    }

addAll方法

    /**
     * 将Collection实现类实例c中的所有元素添加到该linkedList内部的链表中。
     * 注意是添加到内部链表的尾部。如果在添加的过程中c中元素有修改的话那么可能导致
     * 结果的不可预知性。
     * 该方法使用带参数的addAll方法插入到链表的最后的位置。
     */
    public boolean addAll(Collection<? extends E> c) 
    {
        return addAll(size, c);
    }

    /**
     * 将Collection实现类c中的所有元素插入到指定的index位置。并将[index,size-1]位置的所有元素
     * 后移,当然这里相比ArrayList实现要轻量许多,只需要改动一处的指针就可以实现这些元素的后移。
     * 1、检查传入的index是否合理,合理的范围是[0,size]。通过 checkPositionIndex实现。如果
     *   不在该范围内,将抛出IndexOutOfBoundsException。
     * 2、将集合中的元素得到其拷贝数组的形式。该方法执行过后c中的修改将对该集合链表没有影响了。
     *	  该方法执行前或者执行中都可能对该方法的执行产生影响。
     * 3、通过node方法定位到index位置处的元素节点。并记录该节点为succ,它的前驱节点为pred。
     * 4、将c中的元素构造成Node节点依次添加到pred的后面。最后将pred.next指向原来index位置的结点。
     * 我们用succ保存了下来。
     * 5、注意如果pred或者succ为null的情况要同时更新头指针和尾指针。
     * 6、如果添加成功,则返回true,如果c中不包含元素那么返回false。
     */
    public boolean addAll(int index, Collection<? extends E> c) 
    {
        checkPositionIndex(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;

        Node<E> pred, succ;
        if (index == size)
        {
            succ = null;
            pred = last;
        }
        else
        {
            succ = node(index);
            pred = succ.prev;
        }

        for (Object o : a) 
        {
            @SuppressWarnings("unchecked") E e = (E) o;
            Node<E> newNode = new Node<>(pred, e, null);
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            pred = newNode;
        }

        if (succ == null) 
        {
            last = pred;
        }
        else 
        {
            pred.next = succ;
            succ.prev = pred;
        }

        size += numNew;
        modCount++;
        return true;
    }

    /**
     * 检查要插入的index位置是否合理。合理的返回是[0,size],该方法通过isPositionIndex(index)返回的
     * boolean类型的值判断。这些方法只能内部使用。
     */
    private void checkPositionIndex(int index)
    {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private boolean isPositionIndex(int index) 
    {
        return index >= 0 && index <= size;
    }

    /**
     * 该方法返回当检查插入index不合理是返回的错误信息。
     */
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    /**
     * 返回下标在index处的结点。
     * 该方法进行了一定的优化,如果index<=size(链表中元素数量),那么使用头结点遍历寻找
     * 否则使用尾结点遍历寻找。
     * 由于链表不支持随机访问,因此该方法不能像ArrayList中以常数时间复杂度取得。
     */
    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;
        }
    }

addFirst方法

    /**
     * 将元素e添加至链表的最前面,使用linkFirst添加。
     */
    public void addFirst(E e) 
    {
        linkFirst(e);
    }

    /**
     * 将元素放到到链表的最前面,使之成为首节点。该方法为private,只能供LinkedList内部使用
     */
    private void linkFirst(E e) 
    {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        //当前链表为空,那么尾指针也指向该节点。因为该节点是唯一的结点。
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

offerFirst方法

    /**
     * 将元素e添加到链表的最前面。使用addFirst完成。
     */
    public boolean offerFirst(E e)
    {
        addFirst(e);
        return true;
    }

addLast方法

    /**
     * 将元素e添加至链表的最后面,使用linkLast添加。
     */
    public void addLast(E e) 
    {
        linkLast(e);
    }


offerLast方法

    /**
     * 添加元素e到链表的尾部,使用addLast方法完成。
     */
    public boolean offerLast(E e) 
    {
        addLast(e);
        return true;
    }

链表信息类

size方法

    /**
     * 返回链表中存放了多少个元素。该方法直接返回内部的成员变量size,是常数级的。
     */
    public int size()
    {
        return size;
    }

查询元素

indexOf方法

    /**
     * 从链表的头结点开始遍历,如果要查询的元素为null,那么就从头结点查找第一个结点中存放的元素(item)为
     * null的结点,找到返回其下标。
     * 如果要查询的元素不为null,那么从头结点使用equals方法遍历链表中的结点内部的item是否与之相等。
     * 找到返回其下标。
     * 如果都没有赵到,返回-1。
     */
    public int indexOf(Object o) 
    {
        int index = 0;
        if (o == null) 
        {
            for (Node<E> x = first; x != null; x = x.next) 
            {
                if (x.item == null)
                    return index;
                index++;
            }
        }
        else
        {
            for (Node<E> x = first; x != null; x = x.next)
            {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }

lastIndexOf方法

    /**
     * 该方法使用尾结点从链表的尾部开始遍历寻找与o相等或者等于null(o=null)的结点的下标值。
     * 如果找到返回其下标,否则返回-1。
     */
    public int lastIndexOf(Object o) 
    {
        int index = size;
        if (o == null) 
        {
            for (Node<E> x = last; x != null; x = x.prev) 
            {
                index--;
                if (x.item == null)
                    return index;
            }
        }
        else
        {
            for (Node<E> x = last; x != null; x = x.prev)
            {
                index--;
                if (o.equals(x.item))
                    return index;
            }
        }
        return -1;
    }

contains方法

    /**
     * 判断linkedList的链表中是否包含指定的元素,该方法借助indexOf完成,如果返回-1,那么说明不包含。返回false.
     * 否则返回true。
     */
    public boolean contains(Object o) 
    {
        return indexOf(o) != -1;
    }

设置元素

set方法

    /**
     * 替换指定位置处的元素节点内的item。该方法并不新建一个节点,而只是替换节点内部的item信息。
     * 首先要检查传入的index是否合理,合理的范围值[0,size-1]。
     * 如果通过了检查那么将通过node方法定位index处节点。然后修改该节点的item信息。
     */
    public E set(int index, E element) 
    {
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
    }

LinkedList内部的迭代器实现

获取迭代器

    /**
     * 该方法将返回一个ListIterator<E>实现类,指定的index可以从链表的任意位置遍历
     * 首先要检查传入的index的合理性。合理的范围是[0,size],注意size也可以,但是不会遍历
     * 到任何的元素。这个list-iterator也是支持fail-fast机制的。
     */
    public ListIterator<E> listIterator(int index) 
    {
        checkPositionIndex(index);
        return new ListItr(index);
    }
    /**
     * 该方法将返回一个Iterator的实现类用于倒序的遍历集合中的元素。
     */
    public Iterator<E> descendingIterator() 
    {
        return new DescendingIterator();
    }

LinkedList的ListIterator内部实现

    private class ListItr implements ListIterator<E>
    {
        private Node<E> lastReturned;
        private Node<E> next;
        private int nextIndex;
        private int expectedModCount = modCount;

        ListItr(int index) 
        {
            // 如何传入size,将不会遍历到任何元素,
            //否则使用node定位节点。
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }

        public boolean hasNext() 
        {
            return nextIndex < size;
        }

        public E next() 
        {
            //检查是否在迭代器创建了之后,除了通过迭代器本身是否进行了结构化修改。如何是,马上抛出异常
            checkForComodification();
            if (!hasNext())
                throw new NoSuchElementException();

            lastReturned = next;
            next = next.next;
            nextIndex++;
            return lastReturned.item;
        }

        public boolean hasPrevious() 
        {
            return nextIndex > 0;
        }

        public E previous() 
        {
            //检查是否在迭代器创建了之后,除了通过迭代器本身是否进行了结构化修改。如何是,马上抛出异常
            checkForComodification();
            if (!hasPrevious())
                throw new NoSuchElementException();

            lastReturned = next = (next == null) ? last : next.prev;
            nextIndex--;
            return lastReturned.item;
        }

        public int nextIndex() 
        {
            return nextIndex;
        }

        public int previousIndex() 
        {
            return nextIndex - 1;
        }

        public void remove() 
        {
            checkForComodification();
            //还没有遍历任何的元素,此时也不知道该删除谁。
            if (lastReturned == null)
                throw new IllegalStateException();

            //要删除的元素是lastReturned节点。
            Node<E> lastNext = lastReturned.next;
            unlink(lastReturned);
            if (next == lastReturned)
                next = lastNext;
            else
                //保证下次遍历的是删除的结点的下一结点。
                nextIndex--;
            //从这里可以看出不能联系两次执行迭代器的删除操作。这一点
            //从迭代器的注意事项可以看出
            lastReturned = null;
            expectedModCount++;
        }

        public void set(E e) 
        {
            if (lastReturned == null)
                throw new IllegalStateException();
            checkForComodification();
            lastReturned.item = e;
        }

        public void add(E e) 
        {
            checkForComodification();
            lastReturned = null;
            if (next == null)
                linkLast(e);
            else
                linkBefore(e, next);
            nextIndex++;
            expectedModCount++;
        }

        public void forEachRemaining(Consumer<? super E> action) 
        {
            Objects.requireNonNull(action);
            while (modCount == expectedModCount && nextIndex < size) 
            {
                action.accept(next.item);
                lastReturned = next;
                next = next.next;
                nextIndex++;
            }
            checkForComodification();
        }

        final void checkForComodification() 
        {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

LinkedList的DescendingIterator内部实现

由于ListIterator的实现类ListItr既可以正序也可以倒序排列,该方法将倒序排列的实现逻辑委托给了ListItr。内部持有一个ListItr的实例。

这样封装了部分需要的接口,向调用者隐藏了部分接口。

    private class DescendingIterator implements Iterator<E> 
    {
        private final ListItr itr = new ListItr(size());
        public boolean hasNext()
        {
            return itr.hasPrevious();
        }
        public E next() 
        {
            return itr.previous();
        }
        public void remove() 
        {
            itr.remove();
        }
    }

迭代器的注意事项

在获取了迭代器之后,不能连续两次执行remove方法,也不能再执行set方法,因为从代码中可以看出在执行了一次remove方法之后将lastReturned置为了null。如果再次执行将抛出java.lang.IllegalStateException。

    LinkedList<Integer> list = new LinkedList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);

    Iterator<Integer> it = list.iterator();
    while(it.hasNext())
    {
        System.out.println(it.next());
        it.remove();
        it.remove();
    }

如何执意这么做,你将收到一个异常大礼包

<img src="images/iterator_exception.png" alt="迭代器异常" style="margin-left:0px;" />

LinkedList内部的序列化机制

superClone方法

    @SuppressWarnings("unchecked")
    private LinkedList<E> superClone()
    {
        try 
        {
            return (LinkedList<E>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }

clone方法

    /**
     * 返回该list的一个浅复制,就是复制该list一份。但是由于linkedList存放的元素都是引用类型的,因此内部保存的就是引用
     * 的地址。所以复制内部的元素并没有复制。
     */
    public Object clone() 
        LinkedList<E> clone = superClone();

        // Put clone into "virgin" state
        clone.first = clone.last = null;
        clone.size = 0;
        clone.modCount = 0;

        // Initialize clone with our elements
        for (Node<E> x = first; x != null; x = x.next)
            clone.add(x.item);

        return clone;
    }

writeObject方法

    /**
     * 保存LinkedList的状态到一个流中
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException 
    {
        // Write out any hidden serialization magic
        s.defaultWriteObject();

        // Write out size
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (Node<E> x = first; x != null; x = x.next)
            s.writeObject(x.item);
    }

readObject方法

    /**
     * 从流中重建list。
     */
    @SuppressWarnings("unchecked")
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException
    {
        // Read in any hidden serialization magic
        s.defaultReadObject();

        // Read in size
        int size = s.readInt();

        // Read in all elements in the proper order.
        for (int i = 0; i < size; i++)
            linkLast((E)s.readObject());
    }

其他方法

    /**
     * 将元素e插入的节点suss的前面。succ不能为null
     */
    void linkBefore(E e, Node<E> succ) 
    {
        // assert succ != null;
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

    /**
     * 返回一个包含该集合中链表的所有元素的数组。数组的容量=链表中元素的数量
     * 注意该数组是新创建的,外部可以随意的修改,但是通过代码可知,内部的元素仍然是传递的引用的地址值。
     * 所以修改数组中元素的属性会影响到list内部。
     */
    public Object[] toArray() 
    {
        Object[] result = new Object[size];
        int i = 0;
        for (Node<E> x = first; x != null; x = x.next)
            result[i++] = x.item;
        return result;
    }

    /**
     * 该方法通过传入一个泛型类型的数组,如果集合中的元素数量小于传入的数组的容量,那么
     * 就将集合中的元素复制到传入的数组中,此时如果数组中还有剩余空间,那么数组中第size(集合中的元素的数量)
     * 设置为null,以供调用者区分(前提是调用者确定集合中不存在非空元素)。
     * 如果传入的数组不能装下集合中的所有元素,那么就新创建一个与传入数组相同类型的新数组,容量为size。
     *并将集合中的元素复制到新数组中返回。
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) 
    {
        if (a.length < size)
            a = (T[])java.lang.reflect.Array.newInstance(
                                a.getClass().getComponentType(), size);
        int i = 0;
        Object[] result = a;
        for (Node<E> x = first; x != null; x = x.next)
            result[i++] = x.item;

        if (a.length > size)
            a[size] = null;

        return a;
    }

java8新增API

    /** A customized variant of Spliterators.IteratorSpliterator */
    static final class LLSpliterator<E> implements Spliterator<E> 
    {
        static final int BATCH_UNIT = 1 << 10;  // batch array size increment
        static final int MAX_BATCH = 1 << 25;  // max batch array size;
        final LinkedList<E> list; // null OK unless traversed
        Node<E> current;      // current node; null until initialized
        int est;              // size estimate; -1 until first needed
        int expectedModCount; // initialized when est set
        int batch;            // batch size for splits

        LLSpliterator(LinkedList<E> list, int est, int expectedModCount) 
        {
            this.list = list;
            this.est = est;
            this.expectedModCount = expectedModCount;
        }

        final int getEst() 
        {
            int s; // force initialization
            final LinkedList<E> lst;
            if ((s = est) < 0) 
            {
                if ((lst = list) == null)
                    s = est = 0;
                else 
                {
                    expectedModCount = lst.modCount;
                    current = lst.first;
                    s = est = lst.size;
                }
            }
            return s;
        }

        public long estimateSize()
        {
        	return (long) getEst();
        }

        public Spliterator<E> trySplit() 
        {
            Node<E> p;
            int s = getEst();
            if (s > 1 && (p = current) != null) 
            {
                int n = batch + BATCH_UNIT;
                if (n > s)
                    n = s;
                if (n > MAX_BATCH)
                    n = MAX_BATCH;
                Object[] a = new Object[n];
                int j = 0;
                do { a[j++] = p.item; } while ((p = p.next) != null && j < n);
                current = p;
                batch = j;
                est = s - j;
                return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
            }
            return null;
        }

        public void forEachRemaining(Consumer<? super E> action)
        {
            Node<E> p; int n;
            if (action == null) throw new NullPointerException();
            if ((n = getEst()) > 0 && (p = current) != null) 
            {
                current = null;
                est = 0;
                do 
                {
                    E e = p.item;
                    p = p.next;
                    action.accept(e);
                } while (p != null && --n > 0);
            }
            
            if (list.modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

        public boolean tryAdvance(Consumer<? super E> action) 
        {
            Node<E> p;
            if (action == null) throw new NullPointerException();
            if (getEst() > 0 && (p = current) != null) 
            {
                --est;
                E e = p.item;
                current = p.next;
                action.accept(e);
                if (list.modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }

        public int characteristics()
        {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }