死磕JDK源码之LinkedList

Posted sakura1027

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了死磕JDK源码之LinkedList相关的知识,希望对你有一定的参考价值。

LinkedList

LinkedList底层是基于双向链表实现的

内置插入删除方法

linkFirst & linkLast

unlinkFirst & unlinkLast

linkBefore

unlink

源码分析

  1 package java.util;
  2 import java.util.function.Consumer;
  3 public class LinkedList<E> extends AbstractSequentialList<E> implements
  4         List<E>, Deque<E>, Cloneable, java.io.Serializable {
  5     //元素个数
  6     transient int size = 0;
  7     //第一个节点
  8     transient Node<E> first;
  9     //最后一个节点
 10     transient Node<E> last;
 11     //默认构造方法
 12     public LinkedList() {
 13     }
 14     //构造一个包含指定c元素的列表(元素按c迭代器返回的顺序排列)
 15     public LinkedList(Collection<? extends E> c) {
 16         this();
 17         addAll(c);
 18     }
 19     //把节点e置为头节点
 20     private void linkFirst(E e) {
 21         //1.得到第一个节点引用的拷贝
 22         final Node<E> f = first;
 23         //2.把e的后继节点置为f(添加e之前的第一个节点)
 24         final Node<E> newNode = new Node<>(null, e, f);
 25         //3.把e置为first
 26         first = newNode;
 27         //4.如果f为空节点,就把e也置为last,否则把f的前驱节点置为e
 28         if (f == null)
 29             last = newNode;
 30         else
 31             f.prev = newNode;
 32         //5.size modCount+1
 33         size++;
 34         modCount++;
 35     }
 36     //把节点e置为尾节点
 37     void linkLast(E e) {
 38         final Node<E> l = last;
 39         //1.把e的前驱节点置为l(添加e之前的最后一个节点)
 40         final Node<E> newNode = new Node<>(l, e, null);
 41         //2.把e置为last
 42         last = newNode;
 43         //3.如果l为空节点,就把e也置为first,否则把l的后继节点置为e
 44         if (l == null)
 45             first = newNode;
 46         else
 47             l.next = newNode;
 48         size++;
 49         modCount++;
 50     }
 51     //把e放到节点succ之前
 52     void linkBefore(E e, Node<E> succ) {
 53         //1.记录节点succ的前驱节点为pred
 54         final Node<E> pred = succ.prev;
 55         //2.把节点e插入succ之前
 56         final Node<E> newNode = new Node<>(pred, e, succ);
 57         //3.把节点succ的前驱节点置为e
 58         succ.prev = newNode;
 59         //4.如果pred为空节点,就把e也置为first,否则把pred的后继节点置为e
 60         if (pred == null)
 61             first = newNode;
 62         else
 63             pred.next = newNode;
 64         size++;
 65         modCount++;
 66     }
 67     //移除头节点f
 68     private E unlinkFirst(Node<E> f) {
 69         //1.f为第一个节点且f不为空,element为f存放的值
 70         final E element = f.item;
 71         //2.得到f的下一个节点的一个引用(在f.next置为null之前拷贝一份)
 72         final Node<E> next = f.next;
 73         //3.把f存放的值和next域置为null
 74         f.item = null;
 75         f.next = null;
 76         //4.把next引用置为first
 77         first = next;
 78         //5.如果next为空,说明没有元素了,那么把last也置为空
 79         if (next == null)
 80             last = null;
 81         //否则把next的前驱引用置为null
 82         else
 83             next.prev = null;
 84         //6.size-1 modCount+1
 85         size--;
 86         modCount++;
 87         //7.返回被移除的头节点的值
 88         return element;
 89     }
 90     //移除尾节点l
 91     private E unlinkLast(Node<E> l) {
 92         //得到尾节点存放的值
 93         final E element = l.item;
 94         //得到尾节点的前一个节点的引用的一份拷贝
 95         final Node<E> prev = l.prev;
 96         //把尾节点的值置为null
 97         l.item = null;
 98         //把尾节点的前驱引用置为null
 99         l.prev = null;
100         //把prev引用置为last
101         last = prev;
102         //如果prev为空,说明没有元素了,那么把first也置为空
103         if (prev == null)
104             first = null;
105         //否则把prev的后继引用置为null
106         else
107             prev.next = null;
108         size--;
109         modCount++;
110         //返回被移除尾节点的值
111         return element;
112     }
113     //移除x节点,x不为null
114     E unlink(Node<E> x) {
115         //1.得到节点x存放的值
116         final E element = x.item;
117         //2.得到x后继节点引用的一份拷贝
118         final Node<E> next = x.next;
119         //3.得到x前驱节点引用的一份拷贝
120         final Node<E> prev = x.prev;
121         //如果prev为空,即节点x为第一个节点
122         if (prev == null) {
123             first = next;
124         //4.prev不为空,把x前驱节点的next指向x的后继节点
125         } else {
126             prev.next = next;
127             x.prev = null;
128         }
129         //如果next为空,即节点x为最后一个元素
130         if (next == null) {
131             last = prev;
132         //5.next不为空,把x后继节点的prev指向x的前驱节点
133         } else {
134             next.prev = prev;
135             x.next = null;
136         }
137         //6.把x存放的值置为null
138         x.item = null;
139         //7.size-1 modCount+1
140         size--;
141         modCount++;
142         //8.返回被移除节点x的值
143         return element;
144     }
145     //返回列表第一个节点的值
146     public E getFirst() {
147         final Node<E> f = first;
148         if (f == null)
149             throw new NoSuchElementException();
150         return f.item;
151     }
152     //返回列表最后一个节点的值
153     public E getLast() {
154         final Node<E> l = last;
155         if (l == null)
156             throw new NoSuchElementException();
157         return l.item;
158     }
159     //移除头节点并返回其值
160     public E removeFirst() {
161         final Node<E> f = first;
162         if (f == null)
163             throw new NoSuchElementException();
164         return unlinkFirst(f);
165     }
166     //移除尾节点并返回其值
167     public E removeLast() {
168         final Node<E> l = last;
169         if (l == null)
170             throw new NoSuchElementException();
171         return unlinkLast(l);
172     }
173     //把节点e置为头节点
174     public void addFirst(E e) {
175         linkFirst(e);
176     }
177     //把节点e置为尾节点
178     public void addLast(E e) {
179         linkLast(e);
180     }
181     //判断列表是否包含元素o
182     public boolean contains(Object o) {
183         return indexOf(o) != -1;
184     }
185     //返回元素个数
186     public int size() {
187         return size;
188     }
189     //把节点e添加至列表尾部,添加完成返回true
190     public boolean add(E e) {
191         linkLast(e);
192         return true;
193     }
194     //移除列表中第一次出现的指定元素o,移除完成返回true
195     public boolean remove(Object o) {
196         if (o == null) {
197             for (Node<E> x = first; x != null; x = x.next) {
198                 if (x.item == null) {
199                     unlink(x);
200                     return true;
201                 }
202             }
203         } else {
204             for (Node<E> x = first; x != null; x = x.next) {
205                 if (o.equals(x.item)) {
206                     unlink(x);
207                     return true;
208                 }
209             }
210         }
211         return false;
212     }
213     //添加集合c中的所有元素至列表尾部(按c中迭代器的顺序)
214     public boolean addAll(Collection<? extends E> c) {
215         return addAll(size, c);
216     }
217     //把集合c中的所有元素插入index处
218     public boolean addAll(int index, Collection<? extends E> c) {
219         //1.索引检查
220         checkPositionIndex(index);
221         //2.把带插入的集合转为数组a,如果a的长度为0,直接返回false
222         Object[] a = c.toArray();
223         int numNew = a.length;
224         if (numNew == 0)
225             return false;
226         //3.succ为索引为index的节点,pred为索引为index-1的节点
227         Node<E> pred, succ;
228         //4.如果index为size,那么succ为null,pred为last节点
229         if (index == size) {
230             succ = null;
231             pred = last;
232         } else {
233             succ = node(index);
234             pred = succ.prev;
235         }
236         for (Object o : a) {
237             @SuppressWarnings("unchecked") E e = (E) o;
238             //5.建立e节点的pred引用
239             Node<E> newNode = new Node<>(pred, e, null);
240             //6.如果index=0,即pred为空节点就把first置为e
241             if (pred == null)
242                 first = newNode;
243             //否则把pred的next引用置为e
244             else
245                 pred.next = newNode;
246             pred = newNode;
247         }
248         //7.如果index处为空,就把集合c中的最后一个元素置为last
249         if (succ == null) {
250             last = pred;
251         //否则建立集合c中最后一个元素的next引用为succ,succ的prev引用为pred
252         } else {
253             pred.next = succ;
254             succ.prev = pred;
255         }
256         //8.更新size和modCount
257         size += numNew;
258         modCount++;
259         return true;
260     }
261     //移除所有元素
262     public void clear() {
263         for (Node<E> x = first; x != null;) {
264             Node<E> next = x.next;
265             x.item = null;
266             x.next = null;
267             x.prev = null;
268             x = next;
269         }
270         first = last = null;
271         size = 0;
272         modCount++;
273     }
274     //返回指定位置的元素
275     public E get(int index) {
276         checkElementIndex(index);
277         return node(index).item;
278     }
279     //替换指定index的元素为指定element,并返回被替换的值
280     public E set(int index, E element) {
281         checkElementIndex(index);
282         Node<E> x = node(index);
283         E oldVal = x.item;
284         x.item = element;
285         return oldVal;
286     }
287     //把element插入指定index处
288     public void add(int index, E element) {
289         checkPositionIndex(index);
290         if (index == size)
291             linkLast(element);
292         else
293             linkBefore(element, node(index));
294     }
295     //移除指定位置的元素
296     public E remove(int index) {
297         checkElementIndex(index);
298         return unlink(node(index));
299     }
300     //检查index是否越界
301     private boolean isElementIndex(int index) {
302         return index >= 0 && index < size;
303     }
304     //检查index是否越界
305     private boolean isPositionIndex(int index) {
306         return index >= 0 && index <= size;
307     }
308     //索引越界错误处理
309     private String outOfBoundsMsg(int index) {
310         return "Index: " + index + ", Size: " + size;
311     }
312     //索引检查
313     private void checkElementIndex(int index) {
314         if (!isElementIndex(index))
315             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
316     }
317     //索引检查
318     private void checkPositionIndex(int index) {
319         if (!isPositionIndex(index))
320             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
321     }
322     //返回index处的节点
323     Node<E> node(int index) {
324         //index在前半部分从前向后遍历
325         if (index < (size >> 1)) {
326             Node<E> x = first;
327             for (int i = 0; i < index; i++)
328                 x = x.next;
329             return x;
330         //否则从后向前遍历
331         } else {
332             Node<E> x = last;
333             for (int i = size - 1; i > index; i--)
334                 x = x.prev;
335             return x;
336         }
337     }
338     //返回列表中第一次出现指定元素o的索引,不存在返回-1
339     public int indexOf(Object o) {
340         int index = 0;
341         if (o == null) {
342             for (Node<E> x = first; x != null; x = x.next) {
343                 if (x.item == null)
344                     return index;
345                 index++;
346             }
347         } else {
348             for (Node<E> x = first; x != null; x = x.next) {
349                 if (o.equals(x.item))
350                     return index;
351                 index++;
352             }
353         }
354         return -1;
355     }
356     //返回列表中最后一次出现指定元素o的索引,不存在返回-1
357     public int lastIndexOf(Object o) {
358         int index = size;
359         if (o == null) {
360             for (Node<E> x = last; x != null; x = x.prev) {
361                 index--;
362                 if (x.item == null)
363                     return index;
364             }
365         } else {
366             for (Node<E> x = last; x != null; x = x.prev) {
367                 index--;
368以上是关于死磕JDK源码之LinkedList的主要内容,如果未能解决你的问题,请参考以下文章

死磕 java集合之LinkedList源码分析

死磕JDK源码之Thread

死磕JDK源码之ArrayList

死磕 java集合之LinkedHashMap源码分析

JDK源码之java.util.LinkedList

集合之LinkedList(含JDK1.8源码分析)