美文网首页
LinkedList源码详解

LinkedList源码详解

作者: small瓜瓜 | 来源:发表于2019-05-23 16:31 被阅读0次
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 <E> the type of elements held in this collection
 * @author Josh Bloch
 * @see List
 * @see ArrayList
 * @since 1.2
 */

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


    /***
     * 在源码中,这个内部类是在代码的后面些,提到前面进行说明。
     * Node节点就是LinkedList链表中的节点元素了,该类包含
     * 一个前驱节点引用、一个后继节点引用和节点值,值类型是一个泛型,
     * 只有一个有参构造方法
     */
    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;
        }
    }

    /**
     * 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;

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

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

    /**
     * 生成一个Node节点,将其作为头节点插入集合,
     * 然后将参数e的值设置为节点的值
     */
    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++
        modCount++;
    }

    /**
     * 生成一个Node节点,将其作为尾节点插入集合,
     * 然后将参数e的值设置为节点的值
     */
    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++
        modCount++;
    }

    /**
     * 在非null节点succ之前插入元素e
     */
    void linkBefore(E e, Node<E> succ) {
//         assert succ != null;
//      源码并没有判断succ为空,如果传入空succ
//,则会报错抛出NULLPOINTEXCEPT
        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++
        modCount++;
    }

    /**
     * 取消链接非空的第一个节点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; // 让GC可以收集被断开的对象
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

    /**
     * 取消链接非空的最后一个节点l
     */
    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; // 让GC可以收集被断开的对象
        last = prev;
        if (prev == null)
            first = null;
        else
            prev.next = null;
        size--;
        modCount++;
        return element;
    }

    /**
     * 取消链接非空节点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;
    }

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

    /**
     * 返回此集合中的最后一个元素
     */
    public E getLast() {
        final Node<E> 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<E> 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<E> 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<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;
                }
            }
        }
//        上面的那些代码可能会让人觉得,写的不够简洁,可以写的像如下:
//        for (Node<E> 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<? extends E> c) {
        return addAll(size, c);
    }

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

        Object[] a = c.toArray();
        int numNew = a.length;
//        如果添加进来的集合为空,则直接返回false结束本方法
        if (numNew == 0)
            return false;
//        初始化前驱和后继节点引用对象
        Node<E> 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<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加上插入的元素
        size += numNew;
        modCount++;
        return true;
    }

    /**
     * 从此集合中删除所有元素。
     * 此调用返回后集合将被清空。
     */
    public void clear() {
        // 清除节点之间的所有链接是“不必要的”,
        // 使用for循环将所有引用变量赋值为null,
        // 主要是为了帮助GC优化,防止内存泄漏
        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++;
    }


    // 位置访问操作

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

    /**
     * 用element替换此集合中指定位置的节点上的值
     */
    public E set(int index, E element) {
        checkElementIndex(index);
        Node<E> 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<E> node(int index) {
        // assert isElementIndex(index);

//        为加快查找速度,先判断index是在偏前面还是偏后面,
//        然后在循环查找,时间复杂度从O(n)变成O(n/2)
        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;
        }
    }

    // 搜索操作

    /**
     * 返回指定元素第一次出现的索引
     * 在此集合中,如果此集合不包含该元素,则返回-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<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;
    }

    /**
     * 返回指定元素最后一次出现的索引
     * 在此集合中,如果此集合不包含该元素,则返回-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<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;
    }

    // 队列操作。

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

    /**
     * 检索但不删除此集合的头部(第一个元素)。
     * <p>
     * 和peek()的区别是,该方法如果first为null,则会抛出异常
     */
    public E element() {
        return getFirst();
    }

    /**
     * 检索并删除此集合的头部(第一个元素)。poll轮询
     */
    public E poll() {
        final Node<E> 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}。
     * <p>
     * 与peek()一样
     */
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }

    /**
     * 检索但不删除此集合的最后一个元素,
     * 如果此集合为空,则返回{@code null}。
     */
    public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }

    /**
     * 检索并删除此集合的第一个元素,
     * 如果此集合为空,则返回{@code null}。
     */
    public E pollFirst() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

    /**
     * 检索并删除此集合的最后一个元素,
     * 如果此集合为空,则返回{@code null}。
     */
    public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }

    /**
     * 将元素推送到此集合所表示的堆栈上。其他
     * 单词,在此集合的前面插入元素。
     */
    public void push(E e) {
        addFirst(e);
    }

    /**
     * 弹出此集合所代表的堆栈中的元素。其他
     * words,删除并返回此集合的第一个元素。
     * <p>
     * 此方法相当于{@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<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;
                }
            }
        }
//        int index = lastIndexOf(o);
//        if(index != -1){
//            unlink(node(index));
//            return true;
//        }
//        上面的代码,不写成这样简洁的方式,也是同理,
//        node方法找到index元素,是用for循环到的,增大了时间复杂度
        return false;
    }

    /**
     * 返回此列表中元素的列表迭代器(正确
     * 序列),从列表中的指定位置开始。
     * 遵守{@code List.listIterator(int)}的一般合同
     */
    public ListIterator<E> listIterator(int index) {
        checkPositionIndex(index);
        return new ListItr(index);
    }

    //    内部类作迭代器模式
    private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned;
        private Node<E> 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<E> 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<? super E> 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<E> descendingIterator() {
        return new DescendingIterator();
    }

    /**
     * 适配器通过ListItr.previous提供降序迭代器
     * 从后往前的一个迭代器,双向链表的好处
     */
    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();
        }
    }

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

    /**
     * 返回此{@code LinkedList}的浅表副本。 (要素
     * 他们自己没有被克隆。)
     */
    public Object clone() {
        LinkedList<E> clone = superClone();

        // Put clone into "virgin" state
//        重置为"处女"状态
        clone.first = clone.last = null;
        clone.size = 0;
        clone.modCount = 0;

        // 使用该对象的元素初始化克隆
        for (Node<E> 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<E> x = first; x != null; x = x.next)
            result[i++] = x.item;
        return result;
    }

    /**
     * 返回一个包含此列表中所有元素的数组
     * 正确的顺序(从第一个到最后一个元素);
     * 运行时类型返回的数组是指定类型的数组。
     * 如果数组的大小适合,将元素填入其中。否则,
     * 创建一个新的数组使用指定类型数组进行分配
     * 此列表的大小。
     */
    @SuppressWarnings("unchecked")
    public <T> 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<E> 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<E> 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<E> spliterator() {
        return new LLSpliterator<E>(this, -1, 0);
    }

    /**
     * Spliterators.IteratorSpliterator的自定义变体
     */
    static final class LLSpliterator<E> implements Spliterator<E> {
//      批量数组大小增量,2的10次方等于1024
        static final int BATCH_UNIT = 1 << 10; 
//      最大批量数组大小;2的25次方等于33554432
        static final int MAX_BATCH = 1 << 25;  
        final LinkedList<E> list; // null OK,除非遍历
        Node<E> current;      // 当前节点; null,直到初始化
        int est;              // 规模估计; -1直到第一次需要
        int expectedModCount; // 在est设置时初始化
        int batch;            // 拆分的批量大小

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

        //      获取est的大小,如果是第一次获取,
//      该方法会同时将current、expectedModCount赋值
        final int getEst() {
            int s; // 强制初始化
            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();
//          检查链表的长度是否大于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<? 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;
        }
    }

}

相关文章

网友评论

      本文标题:LinkedList源码详解

      本文链接:https://www.haomeiwen.com/subject/mqmpzqtx.html