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()); }
不能只满足于写完代码运行结果正确就完事,时常考虑如何让代码更加简练更加容易维护、容易扩展和复用,只有这样才可以真正得到提高
--《来自大话设计模式》