java集合框架04——LinkedList和源码分析

上一章学习了ArrayList,并分析了其源码,这一章我们将对LinkedList的具体实现进行详细的学习。依然遵循上一章的步骤,先对LinkedList有个整体的认识,然后学习它的源码,深入剖析LinkedList。

LinkedList简介

    首先看看LinkedList与Collection的关系:

                                                 


    LinkedList的继承关系如下:

java.lang.Object  
   ↳     java.util.AbstractCollection<E>  
         ↳     java.util.AbstractList<E>  
               ↳     java.util.AbstractSequentialList<E>  
                     ↳     java.util.LinkedList<E>  
  
public class LinkedList<E>  
    extends AbstractSequentialList<E>  
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {}  

 LinkedList是一个继承与AbatractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作

        LinkedList实现了List接口,能对它进行队列操作。

        LinkedList实现了Deque接口,即能将LinkedList当作双端队列使用。

        LinkedList实现了Java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

        LinkedList是非同步的

        这里插一句,简单说一下AbstractSequentialList,因为LinkedList是其子类。

        AbstractSequentialList实现了get(int index)、set(int index, E element)、add(int index, E element)和remove(int index)这些方法。这些接口都是随机访问List的,LinkedList是双向链表,既然它继承与AbstractSequentialList,就相当于已经实现了“get(int index)”这些接口,可以支持随机访问了。

        此外,如果我们需要通过AbstractSequentialList实现一个自己的列表,只需要扩展此类,并提供listIterator()和size()方法的实现即可。若要实现不可修改的列表,则需要实现列表迭代器的hashNext、next、hashPrevious、previous和index方法即可。

    下面先总览一下LinkedList的构造函数和API:

LinkedList的API  
boolean       add(E object)  
void          add(int location, E object)  
boolean       addAll(Collection<? extends E> collection)  
boolean       addAll(int location, Collection<? extends E> collection)  
void          addFirst(E object)  
void          addLast(E object)  
void          clear()  
Object        clone()  
boolean       contains(Object object)  
Iterator<E>   descendingIterator()  
E             element()  
E             get(int location)  
E             getFirst()  
E             getLast()  
int           indexOf(Object object)  
int           lastIndexOf(Object object)  
ListIterator<E>     listIterator(int location)  
boolean       offer(E o)  
boolean       offerFirst(E e)  
boolean       offerLast(E e)  
E             peek()  
E             peekFirst()  
E             peekLast()  
E             poll()  
E             pollFirst()  
E             pollLast()  
E             pop()  
void          push(E e)  
E             remove()  
E             remove(int location)  
boolean       remove(Object object)  
E             removeFirst()  
boolean       removeFirstOccurrence(Object o)  
E             removeLast()  
boolean       removeLastOccurrence(Object o)  
E             set(int location, E object)  
int           size()  
<T> T[]       toArray(T[] contents)  
Object[]     toArray()  

  LinkedList包含三个重要的成员:first、last和size:first是双向链表的表头,last是双向链表的尾节点,size是双向链表中的节点个数。

LinkedList源码分析(基于JDK1.7)

        下面通过分析LinkedList的源码更加深入的了解LinkedList原理。由于LinkedList是通过双向链表实现的,所以源码也比较容易理解:

  1 package java.util;  
  2   
  3 /*双向链表*/  
  4 public class LinkedList<E>  
  5     extends AbstractSequentialList<E>  
  6     implements List<E>, Deque<E>, Cloneable, java.io.Serializable  
  7 {  
  8     /** 
  9     * 这里先说一下transient关键字的用法: 
 10     * 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程, 
 11     * 只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化。但是有种情况是有些属性是不需要序列号的,所以就用到这个关键字。 
 12     * 只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。 
 13     */  
 14     transient int size = 0; //LinkedList中元素的个数  
 15     transient Node<E> first; //链表的头结点  
 16     transient Node<E> last; //链表的尾节点  
 17   
 18     public LinkedList() { //默认构造函数,创建一个空链表  
 19     }  
 20   
 21     //按照c中的元素生成一个LinkedList  
 22     public LinkedList(Collection<? extends E> c) {  
 23         this();  
 24         addAll(c); //将c中的元素添加到空链表的尾部  
 25     }  
 26   
 27     /***************************** 添加头结点 ********************************/  
 28     public void addFirst(E e) {  
 29         linkFirst(e);  
 30     }  
 31   
 32     private void linkFirst(E e) {  
 33         final Node<E> f = first; //f指向头结点  
 34         //生成一个新结点e,其前向指针为null,后向指针为f    
 35         final Node<E> newNode = new Node<>(null, e, f);  
 36         first = newNode; //first指向新生成的结点,f保存着老的头结点信息    
 37         if (f == null)  
 38             last = newNode; //如果f为null,则表示整个链表目前是空的,则尾结点也指向新结点  
 39         else  
 40             f.prev = newNode;  
 41         size++;  
 42         modCount++; //修改次数+1  
 43     }  
 44   
 45     /****************** 添加尾节点,与上面添加头结点原理一样 ******************/  
 46     public void addLast(E e) {  
 47         linkLast(e);  
 48     }  
 49   
 50     void linkLast(E e) {  
 51         final Node<E> l = last;  
 52         final Node<E> newNode = new Node<>(l, e, null);  
 53         last = newNode;  
 54         if (l == null)  
 55             first = newNode;  
 56         else  
 57             l.next = newNode;  
 58         size++;  
 59         modCount++;  
 60     }  
 61   
 62     /****************** 在非空节点succ之前插入新节点e ************************/  
 63     void linkBefore(E e, Node<E> succ) {  
 64         // assert succ != null; //外界调用需保证succ不为null,否则程序会抛出空指针异常    
 65         final Node<E> pred = succ.prev;  
 66          //生成一个新结点e,其前向指针指向pred,后向指针指向succ    
 67         final Node<E> newNode = new Node<>(pred, e, succ);  
 68         succ.prev = newNode; //succ的前向指针指向newNode    
 69         if (pred == null)  
 70             //如果pred为null,则表示succ为头结点,此时头结点指向最新生成的结点newNode   
 71             first = newNode;  
 72         else  
 73             //pred的后向指针指向新生成的结点,此时已经完成了结点的插入操作  
 74             pred.next = newNode;  
 75         size++;  
 76         modCount++;  
 77     }  
 78   
 79     /*********************** 删除头结点,并返回头结点的值 *********************/  
 80     public E removeFirst() {  
 81         final Node<E> f = first;  
 82         if (f == null)  
 83             throw new NoSuchElementException();  
 84         return unlinkFirst(f); //private方法  
 85     }  
 86       
 87     private E unlinkFirst(Node<E> f) {  
 88         // assert f == first && f != null; //需确保f为头结点,且链表不为Null    
 89         final E element = f.item; //获得节点的值  
 90         final Node<E> next = f.next; //获得头结点下一个节点  
 91         f.item = null;  
 92         f.next = null; // help GC  
 93         first = next;  
 94         if (next == null)  
 95             //如果next为null,则表示f为last结点,此时链表即为空链表   
 96             last = null;  
 97         else  
 98             //修改next的前向指针,因为first结点的前向指针为null   
 99             next.prev = null;  
100         size--;  
101         modCount++;  
102         return element;  
103     }  
104   
105     /********************** 删除尾节点,并返回尾节点的值 ********************/  
106     public E removeLast() {  
107         final Node<E> l = last;  
108         if (l == null)  
109             throw new NoSuchElementException();  
110         return unlinkLast(l); //private方法  
111     }  
112   
113     private E unlinkLast(Node<E> l) {  
114         // assert l == last && l != null;  
115         final E element = l.item;  
116         final Node<E> prev = l.prev;  
117         l.item = null;  
118         l.prev = null; // help GC  
119         last = prev;  
120         if (prev == null)  
121             first = null;  
122         else  
123             prev.next = null;  
124         size--;  
125         modCount++;  
126         return element;  
127     }  
128   
129     /******************** 删除为空节点x,并返回该节点的值 ******************/  
130     E unlink(Node<E> x) {  
131         // assert x != null; //需确保x不为null,否则后续操作会抛出空指针异常    
132         final E element = x.item;  
133         final Node<E> next = x.next;  
134         final Node<E> prev = x.prev;  
135   
136         if (prev == null) {  
137             //如果prev为空,则x结点为first结点,此时first结点指向next结点(x的后向结点)  
138             first = next;  
139         } else {  
140             prev.next = next; //x的前向结点的后向指针指向x的后向结点    
141             x.prev = null; //释放x的前向指针    
142         }  
143   
144         if (next == null) {  
145             //如果next结点为空,则x结点为尾部结点,此时last结点指向prev结点(x的前向结点)  
146             last = prev;  
147         } else {  
148             next.prev = prev; //x的后向结点的前向指针指向x的前向结点  
149             x.next = null; //释放x的后向指针    
150         }  
151   
152         x.item = null; //释放x的值节点,此时x节点可以完全被GC回收    
153         size--;  
154         modCount++;  
155         return element;  
156     }  
157   
158     /********************** 获得头结点的值 ********************/  
159     public E getFirst() {  
160         final Node<E> f = first;  
161         if (f == null)  
162             throw new NoSuchElementException();  
163         return f.item;  
164     }  
165   
166     /********************** 获得尾结点的值 ********************/  
167     public E getLast() {  
168         final Node<E> l = last;  
169         if (l == null)  
170             throw new NoSuchElementException();  
171         return l.item;  
172     }  
173   
174     /*************** 判断元素(值为o)是否在链表中 *************/  
175     public boolean contains(Object o) {  
176         return indexOf(o) != -1; //定位元素  
177     }  
178   
179     //返回元素个数  
180     public int size() {  
181         return size;  
182     }  
183   
184     //向链表尾部添加元素e  
185     public boolean add(E e) {  
186         linkLast(e);  
187         return true;  
188     }  
189   
190     /*************** 删除值为o的元素 *************/  
191     public boolean remove(Object o) {  
192         if (o == null) {  
193             for (Node<E> x = first; x != null; x = x.next) {  
194                 if (x.item == null) { //找到即返回  
195                     unlink(x);  
196                     return true;  
197                 }  
198             }  
199         } else {//o不为空  
200             for (Node<E> x = first; x != null; x = x.next) {  
201                 if (o.equals(x.item)) {  
202                     unlink(x);  
203                     return true;  
204                 }  
205             }  
206         }  
207         return false;  
208     }  
209   
210     /*************** 将集合e中所有元素添加到链表中 *************/  
211     public boolean addAll(Collection<? extends E> c) {  
212         return addAll(size, c);  
213     }  
214     //从index开始,向后添加的  
215     public boolean addAll(int index, Collection<? extends E> c) {  
216         checkPositionIndex(index); //判断index是否越界  
217   
218         Object[] a = c.toArray(); //将集合c转换为数组  
219         int numNew = a.length;  
220         if (numNew == 0)  
221             return false;  
222   
223         Node<E> pred, succ;  
224         if (index == size) {//即index个节点在尾节点后面  
225             succ = null;  
226             pred = last; //pred指向尾节点  
227         } else {  
228             succ = node(index); //succ指向第index个节点  
229             pred = succ.prev; //pred指向succ的前向节点  
230         }  
231   
232         //for循环结束后,a里面的元素都添加到当前链表里了,向后添加  
233         for (Object o : a) {  
234             @SuppressWarnings("unchecked") E e = (E) o;  
235             Node<E> newNode = new Node<>(pred, e, null);  
236             if (pred == null)  
237                 first = newNode; //如果pred为null,则succ为头结点  
238             else  
239                 pred.next = newNode; //pred的后向指针指向新节点  
240             pred = newNode; //pred指向新节点,即往后移动一个节点,用于下一次循环  
241         }  
242   
243         if (succ == null) { //succ为null表示index为尾节点之后  
244             last = pred;  
245         } else {  
246             //pred表示所有元素添加好之后的最后那个节点,此时pred的后向指针指向之前记录的节点,即index处的节点  
247             pred.next = succ;  
248             succ.prev = pred; //之前记录的结点指向添加元素之后的最后结点  
249         }  
250   
251         size += numNew;  
252         modCount++;  
253         return true;  
254     }  
255   
256     /******************** 清空链表 *************************/  
257     public void clear() {  
258         for (Node<E> x = first; x != null; ) {  
259             Node<E> next = x.next;  
260             x.item = null; //释放值结点,便于GC回收    
261             x.next = null; //释放前向指针    
262             x.prev = null; //释放前后指针    
263             x = next; //后向遍历    
264         }  
265         first = last = null; //释放头尾节点  
266         size = 0;  
267         modCount++;  
268     }  
269   
270   
271     /******************* Positional Access Operations ***********************/  
272   
273     //获得第index个节点的值  
274     public E get(int index) {  
275         checkElementIndex(index);  
276         return node(index).item;  
277     }  
278   
279     //设置第index元素的值  
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   
288     //在index个节点之前添加新的节点  
289     public void add(int index, E element) {  
290         checkPositionIndex(index);  
291   
292         if (index == size)  
293             linkLast(element);  
294         else  
295             linkBefore(element, node(index));  
296     }  
297   
298     //删除第index个节点  
299     public E remove(int index) {  
300         checkElementIndex(index);  
301         return unlink(node(index));  
302     }  
303   
304     //判断index是否为链表中的元素下标  
305     private boolean isElementIndex(int index) {  
306         return index >= 0 && index < size;  
307     }  
308   
309     //判断index是否为链表中的元素下标。。。包含了size  
310     private boolean isPositionIndex(int index) {  
311         return index >= 0 && index <= size;  
312     }  
313   
314     private String outOfBoundsMsg(int index) {  
315         return "Index: "+index+", Size: "+size;  
316     }  
317   
318     private void checkElementIndex(int index) {  
319         if (!isElementIndex(index))  
320             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
321     }  
322   
323     private void checkPositionIndex(int index) {  
324         if (!isPositionIndex(index))  
325             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
326     }  
327   
328     //定位index处的节点  
329     Node<E> node(int index) {  
330         // assert isElementIndex(index);  
331         //index<size/2时,从头开始找  
332         if (index < (size >> 1)) {  
333             Node<E> x = first;  
334             for (int i = 0; i < index; i++)  
335                 x = x.next;  
336             return x;  
337         } else { //index>=size/2时,从尾开始找  
338             Node<E> x = last;  
339             for (int i = size - 1; i > index; i--)  
340                 x = x.prev;  
341             return x;  
342         }  
343     }  
344   
345     /*************************** Search Operations *************************/  
346   
347     //返回首次出现指定元素值o的节点索引  
348     public int indexOf(Object o) {  
349         int index = 0;  
350         if (o == null) {  
351             for (Node<E> x = first; x != null; x = x.next) {  
352                 if (x.item == null)  
353                     return index;  
354                 index++;  
355             }  
356         } else {  
357             for (Node<E> x = first; x != null; x = x.next) {  
358                 if (o.equals(x.item))  
359                     return index;  
360                 index++;  
361             }  
362         }  
363         return -1; //没有则返回-1  
364     }  
365   
366     //返回最后一次出现指定元素值o的节点索引  
367     public int lastIndexOf(Object o) {  
368         int index = size;  
369         if (o == null) {  
370             for (Node<E> x = last; x != null; x = x.prev) {  
371                 index--;  
372                 if (x.item == null)  
373                     return index;  
374             }  
375         } else {  
376             for (Node<E> x = last; x != null; x = x.prev) {  
377                 index--;  
378                 if (o.equals(x.item))  
379                     return index;  
380             }  
381         }  
382         return -1;  
383     }  
384   
385     /***************************** Queue operations ***********************/  
386     //下面是与栈和队列相关的操作了  
387     //实现栈的操作,返回第一个元素的值  
388     public E peek() {  
389         final Node<E> f = first;  
390         return (f == null) ? null : f.item; //不删除  
391     }  
392   
393     //实现队列操作,返回第一个节点  
394     public E element() {  
395         return getFirst();  
396     }  
397   
398     //实现栈的操作,弹出第一个节点  
399     public E poll() {  
400         final Node<E> f = first;  
401         return (f == null) ? null : unlinkFirst(f); //删除  
402     }  
403   
404     //实现队列操作,删除节点  
405     public E remove() {  
406         return removeFirst();  
407     }  
408   
409     //添加节点  
410     public boolean offer(E e) {  
411         return add(e);  
412     }  
413   
414     /************************* Deque operations **********************/  
415     //下面都是和双端队列相关的操作了  
416     //添加头结点  
417     public boolean offerFirst(E e) {  
418         addFirst(e);  
419         return true;  
420     }  
421   
422     //添加尾节点  
423     public boolean offerLast(E e) {  
424         addLast(e);  
425         return true;  
426     }  
427   
428     //返回头结点的值  
429     public E peekFirst() {  
430         final Node<E> f = first;  
431         return (f == null) ? null : f.item;  
432      }  
433   
434     //返回尾节点的值  
435     public E peekLast() {  
436         final Node<E> l = last;  
437         return (l == null) ? null : l.item;  
438     }  
439   
440     //弹出头结点  
441     public E pollFirst() {  
442         final Node<E> f = first;  
443         return (f == null) ? null : unlinkFirst(f); //删除  
444     }  
445   
446     //弹出尾节点  
447     public E pollLast() {  
448         final Node<E> l = last;  
449         return (l == null) ? null : unlinkLast(l); //删除  
450     }  
451   
452     //栈操作,添加头结点  
453     public void push(E e) {  
454         addFirst(e);  
455     }  
456   
457     //栈操作,删除头结点  
458     public E pop() {  
459         return removeFirst();  
460     }  
461   
462     //删除第一次出现o的节点  
463     public boolean removeFirstOccurrence(Object o) {  
464         return remove(o);  
465     }  
466   
467     //删除最后一次出现o的节点  
468     public boolean removeLastOccurrence(Object o) {  
469         if (o == null) {  
470             for (Node<E> x = last; x != null; x = x.prev) {  
471                 if (x.item == null) {  
472                     unlink(x);  
473                     return true;  
474                 }  
475             }  
476         } else {  
477             for (Node<E> x = last; x != null; x = x.prev) {  
478                 if (o.equals(x.item)) {  
479                     unlink(x);  
480                     return true;  
481                 }  
482             }  
483         }  
484         return false;  
485     }  
486   
487     /************************* ListIterator ***********************/  
488       
489     public ListIterator<E> listIterator(int index) {  
490         checkPositionIndex(index);  
491         return new ListItr(index); //ListItr是一个双向迭代器  
492     }  
493   
494     //实现双向迭代器  
495     private class ListItr implements ListIterator<E> {  
496         private Node<E> lastReturned = null;//记录当前节点信息  
497         private Node<E> next; //当前节点的后向节点  
498         private int nextIndex; //当前节点的索引  
499         private int expectedModCount = modCount; //修改次数  
500   
501         ListItr(int index) {  
502             // assert isPositionIndex(index);  
503             next = (index == size) ? null : node(index);  
504             nextIndex = index;  
505         }  
506   
507         public boolean hasNext() {  
508             return nextIndex < size;  
509         }  
510   
511         public E next() {  
512             checkForComodification();  
513             if (!hasNext())  
514                 throw new NoSuchElementException();  
515   
516             lastReturned = next; //记录当前节点  
517             next = next.next; //向后移动一个位置  
518             nextIndex++; //节点索引+1  
519             return lastReturned.item; //返回当前节点的值  
520         }  
521   
522         public boolean hasPrevious() {  
523             return nextIndex > 0;  
524         }  
525   
526         //返回前向节点的值  
527         public E previous() {  
528             checkForComodification();  
529             if (!hasPrevious())  
530                 throw new NoSuchElementException();  
531   
532             lastReturned = next = (next == null) ? last : next.prev;  
533             nextIndex--;  
534             return lastReturned.item;  
535         }  
536   
537         public int nextIndex() { //返回当前节点的索引  
538             return nextIndex;  
539         }  
540   
541         public int previousIndex() { //返回当前节点的前一个索引  
542             return nextIndex - 1;  
543         }  
544   
545         public void remove() { //删除当前节点  
546             checkForComodification();  
547             if (lastReturned == null)  
548                 throw new IllegalStateException();  
549   
550             Node<E> lastNext = lastReturned.next;  
551             unlink(lastReturned);  
552             if (next == lastReturned)  
553                 next = lastNext;  
554             else  
555                 nextIndex--;  
556             lastReturned = null;  
557             expectedModCount++;  
558         }  
559   
560         public void set(E e) { //设置当前节点的值  
561             if (lastReturned == null)  
562                 throw new IllegalStateException();  
563             checkForComodification();  
564             lastReturned.item = e;  
565         }  
566   
567         //在当前节点前面插入新节点信息  
568         public void add(E e) {  
569             checkForComodification();  
570             lastReturned = null;  
571             if (next == null)  
572                 linkLast(e);  
573             else  
574                 linkBefore(e, next);  
575             nextIndex++;  
576             expectedModCount++;  
577         }  
578   
579         final void checkForComodification() {  
580             if (modCount != expectedModCount)  
581                 throw new ConcurrentModificationException();  
582         }  
583     }  
584   
585     private static class Node<E> {  
586         E item;  
587         Node<E> next;  
588         Node<E> prev;  
589   
590         Node(Node<E> prev, E element, Node<E> next) {  
591             this.item = element;  
592             this.next = next;  
593             this.prev = prev;  
594         }  
595     }  
596   
597     //返回前向迭代器  
598     public Iterator<E> descendingIterator() {  
599         return new DescendingIterator();  
600     }  
601   
602     //通过ListItr.previous来提供前向迭代器,方向与原来相反  
603     private class DescendingIterator implements Iterator<E> {  
604         private final ListItr itr = new ListItr(size());  
605         public boolean hasNext() {  
606             return itr.hasPrevious();  
607         }  
608         public E next() {  
609             return itr.previous();  
610         }  
611         public void remove() {  
612             itr.remove();  
613         }  
614     }  
615   
616     @SuppressWarnings("unchecked")  
617     private LinkedList<E> superClone() {  
618         try {  
619             return (LinkedList<E>) super.clone();  
620         } catch (CloneNotSupportedException e) {  
621             throw new InternalError();  
622         }  
623     }  
624   
625     //克隆操作,执行浅拷贝,只复制引用,没有复制引用指向的内存  
626     public Object clone() {  
627         LinkedList<E> clone = superClone();  
628   
629         // Put clone into "virgin" state  
630         clone.first = clone.last = null;  
631         clone.size = 0;  
632         clone.modCount = 0;  
633   
634         // Initialize clone with our elements  
635         for (Node<E> x = first; x != null; x = x.next)  
636             clone.add(x.item);  
637   
638         return clone;  
639     }  
640   
641     /*************************** toArray ****************************/  
642     //返回LinkedList的Object[]数组  
643     public Object[] toArray() {  
644         Object[] result = new Object[size];  
645         int i = 0;  
646         for (Node<E> x = first; x != null; x = x.next)  
647             result[i++] = x.item;  
648         return result;  
649     }  
650   
651     //返回LinkedList的模板数组,存储在a中  
652     @SuppressWarnings("unchecked")  
653     public <T> T[] toArray(T[] a) {  
654         if (a.length < size)  
655             //如果a的大小 < LinkedList的元素个数,意味着数组a不能容纳LinkedList的全部元素  
656             //则新建一个T[]数组,T[]的大小为LinkedList大小,并将T[]赋给a  
657             a = (T[])java.lang.reflect.Array.newInstance(  
658                                 a.getClass().getComponentType(), size);  
659         //如果a大小够容纳LinkedList的全部元素  
660         int i = 0;  
661         Object[] result = a;  
662         for (Node<E> x = first; x != null; x = x.next)  
663             result[i++] = x.item;  
664   
665         if (a.length > size)  
666             a[size] = null;  
667   
668         return a;  
669     }  
670   
671     private static final long serialVersionUID = 876323262645176354L;  
672   
673     /************************* Serializable **************************/  
674     //java.io.Serializable的写入函数  
675     //将LinkedList的“容量,所有元素值”写入到输出流中  
676     private void writeObject(java.io.ObjectOutputStream s)  
677         throws java.io.IOException {  
678         // Write out any hidden serialization magic  
679         s.defaultWriteObject();  
680   
681         // Write out size  
682         s.writeInt(size); //写入容量  
683   
684         // Write out all elements in the proper order.  
685         for (Node<E> x = first; x != null; x = x.next) //写入所有数据  
686             s.writeObject(x.item);  
687     }  
688   
689     //java.io.Serializable的读取函数:根据写入方式反向读出  
690     //先将LinkedList的“容量”读出,然后将“所有元素值”读出  
691     @SuppressWarnings("unchecked")  
692     private void readObject(java.io.ObjectInputStream s)  
693         throws java.io.IOException, ClassNotFoundException {  
694         // Read in any hidden serialization magic  
695         s.defaultReadObject();  
696   
697         // Read in size  
698         int size = s.readInt(); //读出容量  
699   
700         // Read in all elements in the proper order.  
701         for (int i = 0; i < size; i++) //读出所有元素值  
702             linkLast((E)s.readObject());  
703     }  
704 }  
View Code

  总结一下:

        1). LinkedList是通过双向链表去实现的。

        2). 从LinkedList的实现方式中可以看出,它不存在容量不足的问题,因为是链表。

        3). LinkedList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写出“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

        4). LinkdedList的克隆函数,即是将全部元素克隆到一个新的LinkedList中。

        5). 由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。

        6). LinkedList可以作为FIFO(先进先出)的队列,作为FIFO的队列时,下标的方法等价:

队列方法       等效方法  
add(e)        addLast(e)  
offer(e)      offerLast(e)  
remove()      removeFirst()  
poll()        pollFirst()  
element()     getFirst()  
peek()        peekFirst()

  7). LinkedList可以作为LIFO(后进先出)的栈,作为LIFO的栈时,下表的方法等价:

栈方法        等效方法  
push(e)      addFirst(e)  
pop()        removeFirst()  
peek()       peekFirst()  

LinkedList遍历方式

        LinkedList支持多种遍历方式,建议不要采用随机访问的方式去遍历LinkedList,而采用逐个遍历的方式。下面我们来看看每种遍历方式:

    1). 通过Iterator迭代器遍历

for(Iterator iter = list.iterator(); iter.hasNext();)  
    iter.next();  

 2). 通过快速随机访问遍历

int size = list.size();  
    for (int i=0; i<size; i++) {  
        list.get(i);          
}  

    3). 通过for循环遍历

for (Integer integ:list)  ;  

 4). 通过pollFirst()pollLast()来遍历

while(list.pollFirst() != null) ;  
while(list.pollLast() != null) ;  

 5). 通过removeFirst()removeLast()来遍历

while(list.removeFirst() != null)  
        ;  
while(list.removeLast() != null)  
        ;  

下面通过一个测试用例来测试一下这些方法的效率:

import java.util.Iterator;  
import java.util.LinkedList;  
import java.util.NoSuchElementException;  
  
/* 
 * @description 测试LinkedList的几种遍历方式和效率 
 * @author eson_15 
 */  
public class LinkedListThruTest {  
    public static void main(String[] args) {  
        // 通过Iterator遍历LinkedList  
        iteratorLinkedListThruIterator(getLinkedList()) ;  
          
        // 通过快速随机访问遍历LinkedList  
        iteratorLinkedListThruForeach(getLinkedList()) ;  
  
        // 通过for循环的变种来访问遍历LinkedList  
        iteratorThroughFor2(getLinkedList()) ;  
  
        // 通过PollFirst()遍历LinkedList  
        iteratorThroughPollFirst(getLinkedList()) ;  
  
        // 通过PollLast()遍历LinkedList  
        iteratorThroughPollLast(getLinkedList()) ;  
  
        // 通过removeFirst()遍历LinkedList  
        iteratorThroughRemoveFirst(getLinkedList()) ;  
  
        // 通过removeLast()遍历LinkedList  
        iteratorThroughRemoveLast(getLinkedList()) ;  
    }  
      
    private static LinkedList<Integer> getLinkedList() {  
        LinkedList<Integer> llist = new LinkedList<Integer>();  
        for (int i=0; i<500000; i++)  
            llist.addLast(i);  
  
        return llist;  
    }  
    /** 
     * 通过快迭代器遍历LinkedList 
     */  
    private static void iteratorLinkedListThruIterator(LinkedList<Integer> list) {  
        if (list == null)  
            return ;  
        long start = System.currentTimeMillis();  
          
        for(Iterator<Integer> iter = list.iterator(); iter.hasNext();)  
            iter.next();  
        long end = System.currentTimeMillis();  
        long interval = end - start;  
        System.out.println("iteratorLinkedListThruIterator:" + interval+" ms");  
    }  
  
    /** 
     * 通过快速随机访问遍历LinkedList 
     */  
    private static void iteratorLinkedListThruForeach(LinkedList<Integer> list) {  
        if (list == null)  
            return ;  
        long start = System.currentTimeMillis();   
        int size = list.size();  
        for (int i=0; i<size; i++) {  
            list.get(i);          
        }  
        long end = System.currentTimeMillis();  
        long interval = end - start;  
        System.out.println("iteratorLinkedListThruForeach:" + interval+" ms");  
    }  
  
    /** 
     * 通过另外一种for循环来遍历LinkedList 
     */  
    private static void iteratorThroughFor2(LinkedList<Integer> list) {  
        if (list == null)  
            return ;  
        long start = System.currentTimeMillis();  
          
        for (Integer integ : list)   
            ;  
        long end = System.currentTimeMillis();  
        long interval = end - start;  
        System.out.println("iteratorThroughFor2:" + interval+" ms");  
    }  
  
    /** 
     * 通过pollFirst()来遍历LinkedList 
     */  
    private static void iteratorThroughPollFirst(LinkedList<Integer> list) {  
        if (list == null)  
            return ;  
        long start = System.currentTimeMillis();  
        while(list.pollFirst() != null)  
            ;  
        long end = System.currentTimeMillis();  
        long interval = end - start;  
        System.out.println("iteratorThroughPollFirst:" + interval+" ms");  
    }  
  
    /** 
     * 通过pollLast()来遍历LinkedList 
     */  
    private static void iteratorThroughPollLast(LinkedList<Integer> list) {  
        if (list == null)  
            return ;  
        long start = System.currentTimeMillis();  
        while(list.pollLast() != null)  
            ;  
        long end = System.currentTimeMillis();  
        long interval = end - start;  
        System.out.println("iteratorThroughPollLast:" + interval+" ms");  
    }  
  
    /** 
     * 通过removeFirst()来遍历LinkedList 
     */  
    private static void iteratorThroughRemoveFirst(LinkedList<Integer> list) {  
        if (list == null)  
            return ;  
        long start = System.currentTimeMillis();  
        try {  
            while(list.removeFirst() != null)  
                ;  
        } catch (NoSuchElementException e) {  
        }  
        long end = System.currentTimeMillis();  
        long interval = end - start;  
        System.out.println("iteratorThroughRemoveFirst:" + interval+" ms");  
    }  
  
    /** 
     * 通过removeLast()来遍历LinkedList 
     */  
    private static void iteratorThroughRemoveLast(LinkedList<Integer> list) {  
        if (list == null)  
            return ;  
        long start = System.currentTimeMillis();  
        try {  
            while(list.removeLast() != null)  
                ;  
        } catch (NoSuchElementException e) {  
        }  
        long end = System.currentTimeMillis();  
        long interval = end - start;  
        System.out.println("iteratorThroughRemoveLast:" + interval+" ms");  
    }  
  
}  

   测试结果如下:

iteratorLinkedListThruIterator:10 ms  
iteratorLinkedListThruForeach:414648 ms  
iteratorThroughFor2:10 ms  
iteratorThroughPollFirst:8 ms  
iteratorThroughPollLast:10 ms  
iteratorThroughRemoveFirst:7 ms  
iteratorThroughRemoveLast:6 ms  

 由此可见,遍历LinkedList时,使用removeFirst()或removeLast()效率最高。但是用它们遍历会删除原始数据;若只是单纯的取数据,而不删除,建议用迭代器方式或者for-each方式。

 

        无论如何,千万不要用随机访问去遍历LinkedList!除非脑门儿被驴给踢了... ...

        LinkedList源码就讨论这么多,如果错误,欢迎留言指正~

posted @ 2017-02-23 18:02  山河永慕~  阅读(659)  评论(0编辑  收藏  举报