zy19982004--容器学习八:LinkedList源码分析

一.概述

  1. LinkedList继承Deque,所以LinkedList的插入删除操作遵循先进性出FIFO。
  2. LinkedList继承Deque,所以Linkedist实现了Deque的操作,比喻offer peek pollfirst/last等操作。其实这些操作也就是建立在getFirst getLast addFirst addLast removeFirst removeLast这几个操作上的。

 

 .成员变量

Java代码   收藏代码
  1. //头节点  
  2. private transient Entry<E> header = new Entry<E>(nullnullnull);  
  3. private transient int size = 0;  

 

 .节点Entry对象

Java代码   收藏代码
  1. //节点  
  2. private static class Entry<E> {  
  3.     E element;           //当前节点存储的元素  
  4.     Entry<E> next;       //当前节点的下一个节点  
  5.     Entry<E> previous;   //当前节点的上一个节点  
  6.   
  7.     Entry(E element, Entry<E> next, Entry<E> previous) {  
  8.         this.element = element;  
  9.         this.next = next;  
  10.         this.previous = previous;  
  11.     }  
  12. }  

 

 四.构造函数

Java代码   收藏代码
  1. //初始化  
  2. public LinkedList() {  
  3.     header.next = header.previous = header;  
  4. }  

 

 .存数据

Java代码   收藏代码
  1. //默认插入到最后  
  2. public boolean add(E e) {  
  3.     addBefore(e, header);  
  4.     return true;  
  5. }  
  6.   
  7. //把元素e插入最前  
  8. public void addFirst(E e) {  
  9.     //等价于把元素e插入到原第一个节点header.next的前面  
  10.     addBefore(e, header.next);  
  11. }  
  12.   
  13. //把元素e插入最后  
  14. public void addLast(E e) {  
  15.     //等价于把元素e插入到header的前面,因为是双链表  
  16.     addBefore(e, header);  
  17. }  
  18.   
  19. //在指定位置插入元素e,原index处和以后的元素往后移  
  20. public void add(int index, E element) {  
  21.     //index == size,把元素e插入到header的前面  
  22.     //其他情况把元素e插入entry(index)的前面  
  23.     addBefore(element, (index == size ? header : entry(index)));  
  24. }  
  25.   
  26.   
  27. //把元素e插入到指定entry的前面  
  28. private Entry<E> addBefore(E e, Entry<E> entry) {  
  29.     Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);  
  30.     newEntry.previous.next = newEntry;  
  31.     newEntry.next.previous = newEntry;  
  32.     size++;  
  33.     modCount++;  
  34.     return newEntry;  
  35. }  

 

 .取数据

Java代码   收藏代码
  1. //取指定位置的元素  
  2. public E get(int index) {  
  3.     return entry(index).element;  
  4. }  
  5.   
  6. private Entry<E> entry(int index) {  
  7.     if (index < 0 || index >= size)  
  8.         throw new IndexOutOfBoundsException("Index: " + index + ", Size: "  
  9.                 + size);  
  10.     Entry<E> e = header;  
  11.     //在链表中取值时,需要遍历整个链表,  
  12.     //即使优化成遍历半个链表,相对于ArrayList的随机访问,还是慢的  
  13.     if (index < (size >> 1)) {  
  14.         for (int i = 0; i <= index; i++)  
  15.             e = e.next;  
  16.     } else {  
  17.         for (int i = size; i > index; i--)  
  18.             e = e.previous;  
  19.     }  
  20.     return e;  
  21. }  
  22.   
  23. //取第一个节点处的元素  
  24. public E getFirst() {  
  25.     if (size == 0)  
  26.         throw new NoSuchElementException();  
  27.   
  28.     return header.next.element;  
  29. }  
  30. //取最后一个节点处的元素  
  31. public E getLast() {  
  32.     if (size == 0)  
  33.         throw new NoSuchElementException();  
  34.   
  35.     return header.previous.element;  
  36. }  
  37.   
  38. //和ArrayList一样的算法,只是ArrayList遍历数组,LinkedList遍历链表  
  39. public int indexOf(Object o) {  
  40.     int index = 0;  
  41.     if (o == null) {  
  42.         //遍历链表  
  43.         for (Entry e = header.next; e != header; e = e.next) {  
  44.             if (e.element == null)  
  45.                 return index;  
  46.             index++;  
  47.         }  
  48.     } else {  
  49.         for (Entry e = header.next; e != header; e = e.next) {  
  50.             if (o.equals(e.element))  
  51.                 return index;  
  52.             index++;  
  53.         }  
  54.     }  
  55.     return -1;  
  56. }  

 

 六.删数据

Java代码   收藏代码
  1. //remove默认删除第一个位置的元素  
  2. public E remove() {  
  3.     return removeFirst();  
  4. }  
  5.   
  6. public E removeFirst() {  
  7.     return remove(header.next);  
  8. }  
  9.   
  10. public E removeLast() {  
  11.     return remove(header.previous);  
  12. }  
  13.   
  14. //和ArrayList一样的算法,只是ArrayList遍历数组,LinkedList遍历链表  
  15. public boolean remove(Object o) {  
  16.     if (o == null) {  
  17.         for (Entry<E> e = header.next; e != header; e = e.next) {  
  18.             if (e.element == null) {  
  19.                 //转换成remove(Entry)  
  20.                 remove(e);  
  21.                 return true;  
  22.             }  
  23.         }  
  24.     } else {  
  25.         for (Entry<E> e = header.next; e != header; e = e.next) {  
  26.             if (o.equals(e.element)) {  
  27.                 //转换成remove(Entry)  
  28.                 remove(e);  
  29.                 return true;  
  30.             }  
  31.         }  
  32.     }  
  33.     return false;  
  34. }  
  35.   
  36. //转换成remove(Entry)  
  37. public E remove(int index) {  
  38.     return remove(entry(index));  
  39. }  
  40.   
  41. //删除指定节点:删除操作都将落到这个方法上  
  42. private E remove(Entry<E> e) {  
  43.     if (e == header)  
  44.         throw new NoSuchElementException();  
  45.   
  46.     E result = e.element;  
  47.     e.previous.next = e.next;         
  48.     e.next.previous = e.previous;    
  49.     //把节点的三个属性全部置为空  
  50.     e.next = e.previous = null;  
  51.     e.element = null;  
  52.     size--;  
  53.     modCount++;  
  54.     return result;  
  55. }  

 

 .遍历

Java代码   收藏代码
  1. private class ListItr implements ListIterator<E> {  
  2.         private Entry<E> lastReturned = header;  
  3.         private Entry<E> next;  
  4.         private int nextIndex;  
  5.         private int expectedModCount = modCount;  
  6.   
  7.                 //初始化的时候next = header.next;  
  8.         ListItr(int index) {  
  9.             if (index < 0 || index > size)  
  10.                 throw new IndexOutOfBoundsException("Index: " + index  
  11.                         + ", Size: " + size);  
  12.             if (index < (size >> 1)) {  
  13.                 next = header.next;  
  14.                 for (nextIndex = 0; nextIndex < index; nextIndex++)  
  15.                     next = next.next;  
  16.             } else {  
  17.                 next = header;  
  18.                 for (nextIndex = size; nextIndex > index; nextIndex--)  
  19.                     next = next.previous;  
  20.             }  
  21.         }  
  22.                   
  23.         public boolean hasNext() {  
  24.             return nextIndex != size;  
  25.         }  
  26.                 //遍历的时候next = next.next,按照从头往后遍历,也就是FIFO的顺序  
  27.         public E next() {  
  28.             checkForComodification();  
  29.             if (nextIndex == size)  
  30.                 throw new NoSuchElementException();  
  31.   
  32.             lastReturned = next;  
  33.             next = next.next;  
  34.             nextIndex++;  
  35.             return lastReturned.element;  
  36.         }  
  37.   
  38.           
  39.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值