LinkedList源码详解

package java.util;

import java.util.function.Consumer;
/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */


/**
 * LinkedList实现双链表接口。实现所有可选集合操作,并允许所有操作
 * 元素(包括{@code null})所有的操作都按照双链的预期执行集合。
 * 索引到集合中的操作将遍历集合开始或结束,以较接近指定索引的为准。
 * 注意,这个实现不是同步的如果多个线程同时访问一个链表,并且至少
 * 其中一个线程从结构上修改集合,它必须在
 * 外部进行同步。结构修改是包括添加或删除一个或多个元素;仅设置值
 * 元素不是结构修改。这通常是通过自然地同步某些对象来完成封装集合。
 * Java集合框架
 *
 * @param  the type of elements held in this collection
 * @author Josh Bloch
 * @see List
 * @see ArrayList
 * @since 1.2
 */

class LinkedList
        extends AbstractSequentialList
        implements List, Deque, Cloneable, java.io.Serializable {
    //用来记录元素数量
    transient int size = 0;


    /***
     * 在源码中,这个内部类是在代码的后面些,提到前面进行说明。
     * Node节点就是LinkedList链表中的节点元素了,该类包含
     * 一个前驱节点引用、一个后继节点引用和节点值,值类型是一个泛型,
     * 只有一个有参构造方法
     */
    private static class Node {
        E item;
        Node next;
        Node prev;

        Node(Node prev, E element, Node next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

    /**
     * Invariant: (first == null && last == null) ||
     * (first.prev == null && first.item != null)
     * 指向第一个节点的指针。
     */
    transient Node first;

    /**
     * Invariant: (first == null && last == null) ||
     * (last.next == null && last.item != null)
     * 指向最后一个节点的指针。
     */
    transient Node last;

    /**
     * 无参构造方法
     */
    public LinkedList() {
    }

    /**
     * 按照集合的c中元素的顺序构造一个LinkedList
     */
    public LinkedList(Collection c) {
        this();
        addAll(c);
    }

    /**
     * 生成一个Node节点,将其作为头节点插入集合,
     * 然后将参数e的值设置为节点的值
     */
    private void linkFirst(E e) {
        final Node f = first;
        final Node newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
//      链表结构发生改变,modCount++
        modCount++;
    }

    /**
     * 生成一个Node节点,将其作为尾节点插入集合,
     * 然后将参数e的值设置为节点的值
     */
    void linkLast(E e) {
        final Node l = last;
        final Node newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
//      链表结构发生改变,modCount++
        modCount++;
    }

    /**
     * 在非null节点succ之前插入元素e
     */
    void linkBefore(E e, Node succ) {
//         assert succ != null;
//      源码并没有判断succ为空,如果传入空succ
//,则会报错抛出NULLPOINTEXCEPT
        final Node pred = succ.prev;
        final Node newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
//              链表结构发生改变,modCount++
        modCount++;
    }

    /**
     * 取消链接非空的第一个节点f。
     */
    private E unlinkFirst(Node f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node next = f.next;
        f.item = null;
        f.next = null; // 让GC可以收集被断开的对象
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

    /**
     * 取消链接非空的最后一个节点l
     */
    private E unlinkLast(Node l) {
        // assert l == last && l != null;
        final E element = l.item;
        final Node prev = l.prev;
        l.item = null;
        l.prev = null; // 让GC可以收集被断开的对象
        last = prev;
        if (prev == null)
            first = null;
        else
            prev.next = null;
        size--;
        modCount++;
        return element;
    }

    /**
     * 取消链接非空节点x
     */
    E unlink(Node x) {
        // assert x != null;
        final E element = x.item;
        final Node next = x.next;
        final Node 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;
    }

    /**
     * 返回此集合中的第一个元素
     */
    public E getFirst() {
        final Node f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

    /**
     * 返回此集合中的最后一个元素
     */
    public E getLast() {
        final Node l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

    /**
     * 从此集合中删除并返回第一个元素。
     *
     * @return the first element from this list
     * @throws NoSuchElementException if this list is empty
     */
    public E removeFirst() {
        final Node f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    /**
     * 从此集合中删除并返回最后一个元素
     *
     * @return the last element from this list
     * @throws NoSuchElementException if this list is empty
     */
    public E removeLast() {
        final Node l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

    /**
     * 在此集合的开头插入指定的元素.
     *
     * @param e the element to add
     */
    public void addFirst(E e) {
        linkFirst(e);
    }

    /**
     * 将指定的元素追加到此集合的末尾.
     * 本方法相当于add
     */
    public void addLast(E e) {
        linkLast(e);
    }

    /**
     * 如果此集合包含指定的元素,则返回{@code true}。
     * 更正式的是,当且仅当此集合至少包含一个元素{@code e},当
     * (o==null?e==null:o.equals(e))时,才返回{@code true}
     */
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

    /**
     * 返回此集合中的元素数。
     */
    public int size() {
        return size;
    }

    /**
     * 将指定的元素追加到此集合的末尾。
     */
    public boolean add(E e) {
//        add方法就是调用了linkLast方法,将元素添加的最后
        linkLast(e);
        return true;
    }

    /**
     * 从此集合中删除第一次出现的指定元素,
     * 如果它存在。如果此集合不包含该元素,则为
     * 不变。
     */
    public boolean remove(Object o) {
        if (o == null) {
            for (Node x = first; x != null; x = x.next) {
                if (x.item == null) {
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node x = first; x != null; x = x.next) {
                if (o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
//        上面的那些代码可能会让人觉得,写的不够简洁,可以写的像如下:
//        for (Node x = first; x != null; x = x.next) {
//            if (Objects.equals(o, x.item)) {
//                unlink(x);
//                return true;
//            }
//        }
//        如果您有此疑问的话,说明您的逻辑能力很厉害,但是缺乏实际的考虑,
//        代码的简洁不代表效率高,就如上面的代码时间复杂度是O(n)级别的,
//        Objects.equals(o, x.item)看似很简洁但是内部判断
//        (a == b) || (a != null && a.equals(b))
//        复杂,在复杂度为O(n)的循环里,每一个语句都将可能执行n次,
//        作为一次就可判断的,我们就要考虑像源码写的那样了
        return false;
    }

    /**
     * 将指定集合中的所有元素追加到末尾此集合,详细信息等到讲解addAll(size, c)时再说明
     */
    public boolean addAll(Collection c) {
        return addAll(size, c);
    }

    /**
     * 将指定集合中的所有元素插入到此中
     * 集合, 同时在指定的位置开始.  移动元素
     * 目前在该位置(如果有)以及任何后续元素
     */
    public boolean addAll(int index, Collection c) {
//        检查index是否满足:index >= 0 && index <= size;
        checkPositionIndex(index);

        Object[] a = c.toArray();
        int numNew = a.length;
//        如果添加进来的集合为空,则直接返回false结束本方法
        if (numNew == 0)
            return false;
//        初始化前驱和后继节点引用对象
        Node pred, succ;
        if (index == size) {
            succ = null;
            pred = last;
        } else {
//          node方法通过循环获取并返回第index个位置的元素
            succ = node(index);
            pred = succ.prev;
        }

//        通过增强for循环,将a中的所以元素添加进集合中
        for (Object o : a) {
            @SuppressWarnings("unchecked") E e = (E) o;
            Node 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加上插入的元素
        size += numNew;
        modCount++;
        return true;
    }

    /**
     * 从此集合中删除所有元素。
     * 此调用返回后集合将被清空。
     */
    public void clear() {
        // 清除节点之间的所有链接是“不必要的”,
        // 使用for循环将所有引用变量赋值为null,
        // 主要是为了帮助GC优化,防止内存泄漏
        for (Node x = first; x != null; ) {
            Node next = x.next;
            x.item = null;
            x.next = null;
            x.prev = null;
            x = next;
        }
        first = last = null;
        size = 0;
        modCount++;
    }


    // 位置访问操作

    /**
     * 返回此集合中指定位置的元素。
     */
    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }

    /**
     * 用element替换此集合中指定位置的节点上的值
     */
    public E set(int index, E element) {
        checkElementIndex(index);
        Node x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
    }

    /**
     * 将指定元素插入此集合中的指定位置。
     * 移动当前在该位置的元素(如果有的话)和任何
     * 右边的后续元素(在其索引中添加一个)。
     */
    public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
//            将元素加到最后面
            linkLast(element);
        else
//            插入到指定位置
            linkBefore(element, node(index));
    }

    /**
     * 删除此集合中指定位置的元素。转移任何
     * 左边的后续元素(从索引中减去一个)。
     * 返回从集合中删除的元素。
     */
    public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }

    /**
     * 判断参数是否是现有元素的索引。
     */
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }

    /**
     * 判断参数是否是有效位置的索引
     * 迭代器或添加操作。
     */
    private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
    }

    /**
     * 构造一个IndexOutOfBoundsException详细消息。
     * 在错误处理代码的许多可能的重构中,
     * 这种“概述”在服务器和客户端虚拟机上表现最佳。
     */
    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", Size: " + size;
    }


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

    private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * Returns指定元素索引处的(非null)节点。
     */
    Node node(int index) {
        // assert isElementIndex(index);

//        为加快查找速度,先判断index是在偏前面还是偏后面,
//        然后在循环查找,时间复杂度从O(n)变成O(n/2)
        if (index < (size >> 1)) {
            Node x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

    // 搜索操作

    /**
     * 返回指定元素第一次出现的索引
     * 在此集合中,如果此集合不包含该元素,则返回-1。
     * 更正式地,返回最低索引{@code i}
     * 如果有(o == null ? get(i)== null: o.equals(get(i)))则返回i
     * 没有这样的索引返回-1。
     */
    public int indexOf(Object o) {
        int index = 0;
//      这里与remove类似
        if (o == null) {
            for (Node x = first; x != null; x = x.next) {
                if (x.item == null)
                    return index;
                index++;
            }
        } else {
            for (Node x = first; x != null; x = x.next) {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }

    /**
     * 返回指定元素最后一次出现的索引
     * 在此集合中,如果此集合不包含该元素,则返回-1。
     * 更正式地,返回最高指数{@code i}
     * 如果有(o == null ? get(i)== null: o.equals(get(i)))则返回i
     * 或-1如果没有这样的索引。
     */
    public int lastIndexOf(Object o) {
        int index = size;
        if (o == null) {
            for (Node x = last; x != null; x = x.prev) {
                index--;
                if (x.item == null)
                    return index;
            }
        } else {
            for (Node x = last; x != null; x = x.prev) {
                index--;
                if (o.equals(x.item))
                    return index;
            }
        }
        return -1;
    }

    // 队列操作。

    /**
     * 检索但不删除此集合的头部(第一个元素)。
     * 

* 返回头节点的值 */ public E peek() { final Node f = first; return (f == null) ? null : f.item; } /** * 检索但不删除此集合的头部(第一个元素)。 *

* 和peek()的区别是,该方法如果first为null,则会抛出异常 */ public E element() { return getFirst(); } /** * 检索并删除此集合的头部(第一个元素)。poll轮询 */ public E poll() { final Node f = first; return (f == null) ? null : unlinkFirst(f); } /** * 检索并删除此集合的头部(第一个元素)。 */ public E remove() { return removeFirst(); } /** * 将指定的元素添加为此集合的尾部(最后一个元素)。 */ public boolean offer(E e) { return add(e); } // Deque operations /** * 在指定集合的前面插入指定的元素。 */ public boolean offerFirst(E e) { addFirst(e); return true; } /** * 在此集合的末尾插入指定的元素。 */ public boolean offerLast(E e) { addLast(e); return true; } /** * 检索但不删除此集合的第一个元素, * 如果此集合为空,则返回{@code null}。 *

* 与peek()一样 */ public E peekFirst() { final Node f = first; return (f == null) ? null : f.item; } /** * 检索但不删除此集合的最后一个元素, * 如果此集合为空,则返回{@code null}。 */ public E peekLast() { final Node l = last; return (l == null) ? null : l.item; } /** * 检索并删除此集合的第一个元素, * 如果此集合为空,则返回{@code null}。 */ public E pollFirst() { final Node f = first; return (f == null) ? null : unlinkFirst(f); } /** * 检索并删除此集合的最后一个元素, * 如果此集合为空,则返回{@code null}。 */ public E pollLast() { final Node l = last; return (l == null) ? null : unlinkLast(l); } /** * 将元素推送到此集合所表示的堆栈上。其他 * 单词,在此集合的前面插入元素。 */ public void push(E e) { addFirst(e); } /** * 弹出此集合所代表的堆栈中的元素。其他 * words,删除并返回此集合的第一个元素。 *

* 此方法相当于{@link #removeFirst()}。 */ public E pop() { return removeFirst(); } /** * 删除此中第一次出现的指定元素 * list(从头到尾遍历集合时)。如果是集合不包含 * 该元素,则不变。 */ public boolean removeFirstOccurrence(Object o) { return remove(o); } /** * 删除此中最后一次出现的指定元素 * list(从头到尾遍历集合时)。如果是集合不包含 * 该元素,则不变。 */ public boolean removeLastOccurrence(Object o) { if (o == null) { for (Node x = last; x != null; x = x.prev) { if (x.item == null) { unlink(x); return true; } } } else { for (Node x = last; x != null; x = x.prev) { if (o.equals(x.item)) { unlink(x); return true; } } } // int index = lastIndexOf(o); // if(index != -1){ // unlink(node(index)); // return true; // } // 上面的代码,不写成这样简洁的方式,也是同理, // node方法找到index元素,是用for循环到的,增大了时间复杂度 return false; } /** * 返回此列表中元素的列表迭代器(正确 * 序列),从列表中的指定位置开始。 * 遵守{@code List.listIterator(int)}的一般合同 */ public ListIterator listIterator(int index) { checkPositionIndex(index); return new ListItr(index); } // 内部类作迭代器模式 private class ListItr implements ListIterator { private Node lastReturned; private Node next; private int nextIndex; // 该类在被创建的时候,初始化expectedModCount = modCount private int expectedModCount = modCount; ListItr(int index) { // assert isPositionIndex(index); next = (index == size) ? null : node(index); nextIndex = index; } public boolean hasNext() { return nextIndex < size; } public E next() { // 该方法检查modCount != expectedModCount // 不相等抛出ConcurrentModificationException异常 checkForComodification(); if (!hasNext()) throw new NoSuchElementException(); lastReturned = next; next = next.next; // 获取节点元素后,nextIndex自加 nextIndex++; return lastReturned.item; } // 是否有前驱节点 public boolean hasPrevious() { return nextIndex > 0; } // 获取前驱节点 public E previous() { checkForComodification(); if (!hasPrevious()) throw new NoSuchElementException(); // 向前移动lastReturned和next所指向的节点对象相同 lastReturned = next = (next == null) ? last : next.prev; // 获取节点元素后,nextIndex自减 nextIndex--; return lastReturned.item; } public int nextIndex() { return nextIndex; } public int previousIndex() { return nextIndex - 1; } // 移除lastReturned所指向的节点对象, // 如果lastReturned未初始化或迭代器执行了add方法, // lastReturned为null,抛出异常 public void remove() { checkForComodification(); if (lastReturned == null) throw new IllegalStateException(); Node lastNext = lastReturned.next; // 调用了LinkedList里面的方法,改变了列表的结构, // modCount不等于expectedModCount // 所以下面的代码expectedModCount++;重新保证了他们的相等, // 这样做的目的是防止外部直接调用unlink,remove,add等方法 // 改变链表的结构,导致代码出错 unlink(lastReturned); // 如果执行了previous方法,使得next与lastReturned指向同一节点对象 // 同时索引nextIndex也在next与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; } // 添加元素,如已经创建好了迭代器对象,要添加元素, // 不能直接用LinkedList对象的add等方法,要用下面的add方法 public void add(E e) { checkForComodification(); lastReturned = null; if (next == null) linkLast(e); else linkBefore(e, next); nextIndex++; expectedModCount++; } public void forEachRemaining(Consumer action) { Objects.requireNonNull(action); while (modCount == expectedModCount && nextIndex < size) { action.accept(next.item); lastReturned = next; next = next.next; nextIndex++; } checkForComodification(); } // 该方法检查链表的结构是否发生改变, // 且不是通过该迭代器add()或remove()方法 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } /** * @since 1.6 */ public Iterator descendingIterator() { return new DescendingIterator(); } /** * 适配器通过ListItr.previous提供降序迭代器 * 从后往前的一个迭代器,双向链表的好处 */ private class DescendingIterator implements Iterator { private final ListItr itr = new ListItr(size()); public boolean hasNext() { return itr.hasPrevious(); } public E next() { return itr.previous(); } public void remove() { itr.remove(); } } // Cloneable @SuppressWarnings("unchecked") private LinkedList superClone() { try { return (LinkedList) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e); } } /** * 返回此{@code LinkedList}的浅表副本。 (要素 * 他们自己没有被克隆。) */ public Object clone() { LinkedList clone = superClone(); // Put clone into "virgin" state // 重置为"处女"状态 clone.first = clone.last = null; clone.size = 0; clone.modCount = 0; // 使用该对象的元素初始化克隆 for (Node x = first; x != null; x = x.next) clone.add(x.item); return clone; } /** * 返回包含此列表中所有元素的数组 * 按正确的顺序(从第一个元素到最后一个元素)。 */ public Object[] toArray() { Object[] result = new Object[size]; int i = 0; for (Node x = first; x != null; x = x.next) result[i++] = x.item; return result; } /** * 返回一个包含此列表中所有元素的数组 * 正确的顺序(从第一个到最后一个元素); * 运行时类型返回的数组是指定类型的数组。 * 如果数组的大小适合,将元素填入其中。否则, * 创建一个新的数组使用指定类型数组进行分配 * 此列表的大小。 */ @SuppressWarnings("unchecked") public T[] toArray(T[] a) { // 如果数组大小小于size,通过Array的newInstance创建一个数组对象 if (a.length < size) a = (T[]) java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size); int i = 0; Object[] result = a; for (Node x = first; x != null; x = x.next) result[i++] = x.item; // 如果a数组大小大于size,则先将链表的元素添加到数组中, // 然后将数组的下标为size的位置设置为空,但是size后面的位置上的值不变 if (a.length > size) a[size] = null; return a; } private static final long serialVersionUID = 876323262645176354L; /** * 将此{@code LinkedList}实例的状态保存到流中 * (即序列化)。 */ // 实现了java.io.Serializable接口,但是被关键字transient修饰的字段,不会被序列化 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden serialization magic s.defaultWriteObject(); // 先将size写入 s.writeInt(size); // 以正确的顺序写出所有元素。 for (Node x = first; x != null; x = x.next) s.writeObject(x.item); } /** * 从流中重构此{@code LinkedList}实例 * (即反序列化)。 */ @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // 读入任何隐藏的序列化魔法 s.defaultReadObject(); // 因为写入的时候是先写入size,所以读取的时候,也要按照顺序读取 int size = s.readInt(); // 按正确的顺序读入所有元素。 for (int i = 0; i < size; i++) linkLast((E) s.readObject()); } /** * 下面的迭代器,主要作用是将链表节点值分批放入数组 */ @Override public Spliterator spliterator() { return new LLSpliterator(this, -1, 0); } /** * Spliterators.IteratorSpliterator的自定义变体 */ static final class LLSpliterator implements Spliterator { // 批量数组大小增量,2的10次方等于1024 static final int BATCH_UNIT = 1 << 10; // 最大批量数组大小;2的25次方等于33554432 static final int MAX_BATCH = 1 << 25; final LinkedList list; // null OK,除非遍历 Node current; // 当前节点; null,直到初始化 int est; // 规模估计; -1直到第一次需要 int expectedModCount; // 在est设置时初始化 int batch; // 拆分的批量大小 LLSpliterator(LinkedList list, int est, int expectedModCount) { this.list = list; this.est = est; this.expectedModCount = expectedModCount; } // 获取est的大小,如果是第一次获取, // 该方法会同时将current、expectedModCount赋值 final int getEst() { int s; // 强制初始化 final LinkedList 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 trySplit() { Node p; int s = getEst(); // 检查链表的长度是否大于1和头节点是否为null if (s > 1 && (p = current) != null) { int n = batch + BATCH_UNIT; if (n > s) n = s; if (n > MAX_BATCH) n = MAX_BATCH; // 创建一个长度为n的数组 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 action) { Node 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 action) { Node 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; } } }

你可能感兴趣的:(LinkedList源码详解)