• JDK源码阅读--LinkedList


    public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable


    继承了bstractSequentialList类,实现了List、Deque、Cloneable、Serializable接口。
    底层数据结构是链表,增删快,查询慢。先进后出,双向链表。重写了clone方法(只是浅拷贝,不会克隆链表中的元素)。添加的元素是可以重复的。


    字段和构造方法:
     1     //被transient修饰的字段,不会被加入序列化
     2     transient int size = 0;
     3 
     4     /**
     5      * Pointer to first node.第一个节点的指针
     6      * Invariant: (first == null && last == null) ||
     7      *            (first.prev == null && first.item != null)
     8      */
     9     transient Node<E> first;
    10 
    11     /**
    12      * Pointer to last node. 指向最后一个节点的指针
    13      * Invariant: (first == null && last == null) ||
    14      *            (last.next == null && last.item != null)
    15      */
    16     transient Node<E> last;
    17 
    18     /**
    19      * Constructs an empty list.
    20      */
    21     public LinkedList() {
    22     }
    23 
    24     /**
    25      * Constructs a list containing the elements of the specified
    26      * collection, in the order they are returned by the collection's
    27      * iterator.
    28      *
    29      * @param  c the collection whose elements are to be placed into this list
    30      * @throws NullPointerException if the specified collection is null
    31      */
    32     public LinkedList(Collection<? extends E> c) {
    33         this();
    34         addAll(c);
    35     }
    
    
    

    LinkedList数据结构中链表的本质操作:

      1    /**
      2      * Links e as first element.
      3      * 链接e作为第一个元素
      4      */
      5     private void linkFirst(E e) {
      6         //first原先是一个空的节点
      7         final Node<E> f = first;//first:第一个节点的指针
      8         /**
      9          * Node(Node<E> prev, E element, Node<E> next)
     10          * @param prev 前一个节点 也叫前置节点
     11          * @param element 当前节点上的元素
     12          * @param next 下一个节点 也叫后置节点
     13          */
     14         //创建一个没有前置节点,并且当前节点的值为e,并且后置节点为f的节点Node
     15         final Node<E> newNode = new Node<>(null, e, f);
     16         //将创建的newNode节点赋给第一个节点的指针first
     17         first = newNode;
     18         //如果后置节点为空,则也将newNode赋给最后一个节点的指针last;如果后置节点不为空,则将newNode作为 后置节点的前置节点,从而让链表连接起来
     19         if (f == null) {
     20             last = newNode;
     21         }
     22         else {
     23             f.prev = newNode;
     24         }
     25         size++;//链表的长度+1
     26         modCount++;//链表被修改的次数+1
     27     }
     28 
     29     /**
     30      * Links e as last element.
     31      * 链接e作为最后一个元素
     32      */
     33     void linkLast(E e) {
     34         final Node<E> l = last;//last:最后一个节点的指针
     35         /**
     36          * Node(Node<E> prev, E element, Node<E> next)
     37          * @param prev 前一个节点
     38          * @param element 当前节点上的元素
     39          * @param next 下一个节点
     40          */
     41         //创建一个没有后置节点,前置节点为l,当前节点指针指向的值为e的节点newNode
     42         final Node<E> newNode = new Node<>(l, e, null);
     43         last = newNode;
     44         if (l == null) {
     45             //如果前置节点为空,则将该节点作为第一个节点的指针
     46             first = newNode;
     47         }
     48         else {
     49             //如果前置节点不为空,则将newNode作为 前置节点的的后置节点
     50             l.next = newNode;
     51         }
     52         size++;//链表的长度+1
     53         modCount++;//链表被修改的次数+1
     54     }
     55 
     56     /**
     57      * 在非空节点succ之前插入节点e
     58      * Inserts element e before non-null Node succ.
     59      */
     60     void linkBefore(E e, Node<E> succ) {
     61         // assert succ != null;
     62         //获取节点succ原先的前置节点
     63         final Node<E> pred = succ.prev;
     64         //创建一个节点newNode,该节点的前置节点为 节点succ的前置节点,该节点的后置节点为succ
     65         final Node<E> newNode = new Node<>(pred, e, succ);
     66         //将succ节点的前置节点指向newNode节点
     67         succ.prev = newNode;
     68         if (pred == null) {
     69             //如果succ节点原先的前置节点为空,则说明succ节点是第一个节点,则将newNode节点设置为第一个节点
     70             first = newNode;
     71         } else {
     72             //如果succ节点原先的前置节点不为空,则将newNode节点作为succ节点的 原先的节点 的后置节点。
     73             pred.next = newNode;
     74         }
     75         size++;//链表的长度+1
     76         modCount++;//链表被修改的次数+1
     77     }
     78 
     79     /**
     80      * Unlinks non-null first node f.
     81      * 断开非空第一个节点f的链接。断开之后变成两个链表了。
     82      *  从节点f的右侧断开。
     83      *  从节点f的位置开始断开,并将节点f指针指向的值设置为空,并且将节点f的后置节点设置为空。
     84      *  返回节点f指针指向的值。
     85      */
     86     private E unlinkFirst(Node<E> f) {
     87         // assert f == first && f != null;
     88         final E element = f.item;
     89         //获取节点f原先的后置节点
     90         final Node<E> next = f.next;
     91         f.item = null;
     92         f.next = null; // help GC
     93         //将节点f原先的后置节点作为第一个节点(的指针)
     94         first = next;
     95         if (next == null) {
     96             //如果节点f原先的后置节点为null,说明节点f原先就是最后一个节点,将最后一个节点置为null。
     97             last = null;
     98         }else {
     99             //如果节点f原先的后置节点不为null,则将节点f原先的后置节点的 前置节点置为null,从而让链表断开。
    100             next.prev = null;
    101         }
    102         size--;//链表的长度+1
    103         modCount++;//链表被修改的次数+1
    104         return element;
    105     }
    106 
    107     /**
    108      * Unlinks non-null last node l.
    109      * 断开非空的最后一个节点l。
    110      * 从节点l的左侧断开。断开之后变成两个链表了。
    111      */
    112     private E unlinkLast(Node<E> l) {
    113         // assert l == last && l != null;
    114         final E element = l.item;
    115         final Node<E> prev = l.prev;
    116         l.item = null;
    117         l.prev = null; // help GC
    118         last = prev;
    119         if (prev == null)
    120             first = null;
    121         else
    122             prev.next = null;
    123         size--;
    124         modCount++;
    125         return element;
    126     }
    127 
    128     /**
    129      * Unlinks non-null node x.
    130      * 断开非空节点x的链接。相当于去掉节点x
    131      */
    132     E unlink(Node<E> x) {
    133         // assert x != null;
    134         //节点x的指针所指向的值
    135         final E element = x.item;
    136         //节点x的后置节点
    137         final Node<E> next = x.next;
    138         //节点x的后置节点
    139         final Node<E> prev = x.prev;
    140 
    141         if (prev == null) {
    142             //如果节点x原先的前置节点为空,则说明节点x就是第一个节点,则将节点x原先的后置节点作为第一个节点
    143             first = next;
    144         } else {
    145             //如果节点x原先的前置节点不为空,则将节点x的后置节点 作为 节点x原先的前置节点的 后置节点,并将节点x的前置节点置为null
    146             prev.next = next;
    147             x.prev = null;
    148         }
    149 
    150         if (next == null) {
    151             //如果节点x原先的后置节点为空,说明节点x就是最后一个元素,则将节点x原先的前置节点作为最后一个节点
    152             last = prev;
    153         } else {
    154             //如果节点x原先的后置节点不为空,则将节点x原先的前置节点作为 节点x原先后置节点的 前置节点,将节点x的后置节点置为null
    155             next.prev = prev;
    156             x.next = null;
    157         }
    158 
    159         x.item = null;//将节点x指针所指向的值 置为null
    160         size--;//链表长度-1
    161         modCount++;//链表被修改次数+1
    162         return element;//返回节点x原先指针所指向的值
    163     }


     1     /**
     2      * 静态 类 Node<E>  节点  这个类作为节点Node
     3      * @param <E>
     4      */
     5     private static class Node<E> {
     6         E item;//当前节点的的指针指向的值
     7         Node<E> next;//下一个节点的指针
     8         Node<E> prev;//前一个节点的指针
     9 
    10         /**
    11          * 构造方法 Node(Node<E> prev, E element, Node<E> next)
    12          * @param prev 前一个节点
    13          * @param element 当前节点(指针)上的元素
    14          * @param next 下一个节点
    15          */
    16         Node(Node<E> prev, E element, Node<E> next) {
    17             this.item = element;//将element赋值给当前节点item  将element作为为当前节点的指针指向的值
    18             this.next = next;//将next赋给下一个节点  为后置节点初始化
    19             this.prev = prev;//将prev赋给前一个节点   为前置节点初始化
    20         }
    21     }

     添加:

     1     /**
     2      * Inserts the specified element at the beginning of this list.
     3      *  在链表的开始处插入元素e
     4      * @param e 被插入的元素e
     5      */
     6     public void addFirst(E e) {
     7         linkFirst(e);
     8     }
     9 
    10     /**
    11      * Appends the specified element to the end of this list.
    12      * 在链表的末尾追加元素e
    13      * <p>This method is equivalent to {@link #add}.
    14      *
    15      * @param e the element to add
    16      */
    17     public void addLast(E e) {
    18         linkLast(e);
    19     }
    20 
    21 
    22     /**
    23      * Appends all of the elements in the specified collection to the end of
    24      * this list, in the order that they are returned by the specified
    25      * collection's iterator.  The behavior of this operation is undefined if
    26      * the specified collection is modified while the operation is in
    27      * progress.  (Note that this will occur if the specified collection is
    28      * this list, and it's nonempty.)
    29      *
    30      * @param c collection containing elements to be added to this list
    31      * @return {@code true} if this list changed as a result of the call
    32      * @throws NullPointerException if the specified collection is null
    33      */
    34     public boolean addAll(Collection<? extends E> c) {
    35         return addAll(size, c);
    36     }
    37 
    38     /**
    39      * Inserts all of the elements in the specified collection into this
    40      * list, starting at the specified position.  Shifts the element
    41      * currently at that position (if any) and any subsequent elements to
    42      * the right (increases their indices).  The new elements will appear
    43      * in the list in the order that they are returned by the
    44      * specified collection's iterator.
    45      *
    46      * @param index index at which to insert the first element
    47      *              from the specified collection
    48      * @param c collection containing elements to be added to this list
    49      * @return {@code true} if this list changed as a result of the call
    50      * @throws IndexOutOfBoundsException {@inheritDoc}
    51      * @throws NullPointerException if the specified collection is null
    52      */
    53     public boolean addAll(int index, Collection<? extends E> c) {
    54         checkPositionIndex(index);
    55 
    56         Object[] a = c.toArray();
    57         int numNew = a.length;
    58         if (numNew == 0)
    59             return false;
    60 
    61         Node<E> pred, succ;
    62         if (index == size) {
    63             succ = null;
    64             pred = last;
    65         } else {
    66             succ = node(index);
    67             pred = succ.prev;
    68         }
    69 
    70         for (Object o : a) {
    71             @SuppressWarnings("unchecked") E e = (E) o;
    72             Node<E> newNode = new Node<>(pred, e, null);
    73             if (pred == null)
    74                 first = newNode;
    75             else
    76                 pred.next = newNode;
    77             pred = newNode;
    78         }
    79 
    80         if (succ == null) {
    81             last = pred;
    82         } else {
    83             pred.next = succ;
    84             succ.prev = pred;
    85         }
    86 
    87         size += numNew;
    88         modCount++;
    89         return true;
    90     }

     删除:

     1     /**
     2      * Removes and returns the first element from this list. 移除第一个元素
     3      *
     4      * @return the first element from this list 返回被移除的第一个元素
     5      * @throws NoSuchElementException if this list is empty
     6      */
     7     public E removeFirst() {
     8         final Node<E> f = first;
     9         if (f == null)
    10             throw new NoSuchElementException();
    11         return unlinkFirst(f);
    12     }
    13 
    14     /**
    15      * Removes and returns the last element from this list. 移除最后一个元素
    16      *
    17      * @return the last element from this list 返回被移除的第一个元素
    18      * @throws NoSuchElementException if this list is empty
    19      */
    20     public E removeLast() {
    21         final Node<E> l = last;
    22         if (l == null)
    23             throw new NoSuchElementException();
    24         return unlinkLast(l);
    25     }
    26 
    27 
    28 
    29 
    30    /**
    31      * Removes all of the elements from this list.
    32      * 清空链表中的所有元素(也就是清空链表中的所有节点(节点的item、next、prev))
    33      * The list will be empty after this call returns.
    34      */
    35     public void clear() {
    36         // Clearing all of the links between nodes is "unnecessary", but:
    37         // - helps a generational GC if the discarded nodes inhabit
    38         //   more than one generation
    39         // - is sure to free memory even if there is a reachable Iterator
    40         for (Node<E> x = first; x != null; ) {
    41             Node<E> next = x.next;
    42             x.item = null;
    43             x.next = null;
    44             x.prev = null;
    45             x = next;
    46         }
    47         first = last = null;
    48         size = 0;
    49         modCount++;
    50     }
     1     /**
     2      * Removes and returns the first element from this list. 移除第一个元素
     3      *
     4      * @return the first element from this list 返回被移除的第一个元素
     5      * @throws NoSuchElementException if this list is empty
     6      */
     7     public E removeFirst() {
     8         final Node<E> f = first;
     9         if (f == null)
    10             throw new NoSuchElementException();
    11         return unlinkFirst(f);
    12     }
    13 
    14     /**
    15      * Removes and returns the last element from this list. 移除最后一个元素
    16      *
    17      * @return the last element from this list 返回被移除的第一个元素
    18      * @throws NoSuchElementException if this list is empty
    19      */
    20     public E removeLast() {
    21         final Node<E> l = last;
    22         if (l == null)
    23             throw new NoSuchElementException();
    24         return unlinkLast(l);
    25     }

     查询:

     1  /**
     2      * Returns the element at the specified position in this list.
     3      *
     4      * @param index index of the element to return
     5      * @return 返回链表中指定索引位置的元素 the element at the specified position in this list
     6      * @throws IndexOutOfBoundsException {@inheritDoc}
     7      */
     8     public E get(int index) {
     9         checkElementIndex(index);
    10         return node(index).item;//返回指定节点指针所指向的值
    11     }
    12 
    /**
         * Returns the (non-null) Node at the specified element index.返回指定元素索引处的(非空)节点。
         */
        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;
            }
        }
    13 
    14  /**
    15      * Returns the first element in this list.
    16      * 返回LinkedList中的第一个节点的指针所指向的值。
    17      *
    18      * @return 返回LinkedList中的第一个元素。
    19      * @throws NoSuchElementException 如果这个链表为空,则抛出这个异常
    20      */
    21     public E getFirst() {
    22         final Node<E> f = first;
    23         if (f == null) {
    24             throw new NoSuchElementException();
    25         }
    26         return f.item;//返回第一个节点的指针所指向的值
    27     }
    28 
    29     /**
    30      * Returns the last element in this list.
    31      *
    32      * @return 返回LinkedList中的最后一个节点的指针所指向的值。
    33      * @throws NoSuchElementException if this list is empty
    34      */
    35     public E getLast() {
    36         final Node<E> l = last;
    37         if (l == null)
    38             throw new NoSuchElementException();
    39         return l.item;//返回最后一个节点的指针所指向的值
    40     }


    LinkedList作为堆栈的时候:

     1    /**
     2      * Pushes an element onto the stack represented by this list.  In other
     3      * words, inserts the element at the front of this list.
     4      * 将元素推入此列表所表示的堆栈。换句话说,就是在此链表的开头插入元素
     5      * <p>This method is equivalent to {@link #addFirst}.
     6      *
     7      * @param e the element to push
     8      * @since 1.6
     9      */
    10     public void push(E e) {
    11         addFirst(e);
    12     }
    13 
    14     /**
    15      * Pops an element from the stack represented by this list.  In other
    16      * words, removes and returns the first element of this list.
    17      *  从这个列表表示的堆栈中弹出一个元素,换句话说,就是移除并返回此列表的第一个元素。
    18      * <p>This method is equivalent to {@link #removeFirst()}.
    19      *
    20      * @return the element at the front of this list (which is the top
    21      *         of the stack represented by this list)
    22      * @throws NoSuchElementException if this list is empty
    23      * @since 1.6
    24      */
    25     public E pop() {
    26         return removeFirst();
    27     }

     set方法:替换元素

     1     /**
     2      * Replaces the element at the specified position in this list with the
     3      * specified element.
     4      * 将列表中指定位置的元素替换为指定元素。
     5      *
     6      * @param index index of the element to replace
     7      * @param element element to be stored at the specified position
     8      * @return the element previously at the specified position
     9      * @throws IndexOutOfBoundsException {@inheritDoc}
    10      */
    11     public E set(int index, E element) {
    12         checkElementIndex(index);
    13         Node<E> x = node(index);
    14         E oldVal = x.item;
    15         x.item = element;
    16         return oldVal;
    17     }

     将LinkedList转为数组:

     1     /**
     2      *
     3      * @return 返回链表中按照顺序排列的一个数组
     4      */
     5     public Object[] toArray() {
     6         Object[] result = new Object[size];
     7         int i = 0;
     8         //遍历链表中的所有节点,并且将节点所指向的值存放到数组中
     9         for (Node<E> x = first; x != null; x = x.next) {
    10             result[i++] = x.item;
    11         }
    12         return result;
    13     }

     序列化和反序列化:

       /**
         * Saves the state of this {@code LinkedList} instance to a stream (that is, serializes it).
         * 将链表的实例状态保存到一个流中。也就是将链表序列化成一个流。
         * @serialData The size of the list (the number of elements it
         *             contains) is emitted (int), followed by all of its
         *             elements (each an Object) in the proper order.
         */
        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);
        }
    
        /**
         * Reconstitutes this {@code LinkedList} instance from a stream (that is, deserializes it).
         * 从流中重新构造这个实例。也就是将 流反序列化成链表(LinkedList)实例
         */
        @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());
        }
  • 相关阅读:
    css变量
    es6的this指向
    Java面试题(包装类)
    moment笔记
    Class
    CSS斜切角
    Element.getBoundingClientRect()
    Do not mutate vuex store state outside mutation handlers.
    antd不想写那么多option怎么办
    解析URL参数
  • 原文地址:https://www.cnblogs.com/lixianyuan-org/p/10512090.html
Copyright © 2020-2023  润新知