<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    seaairland

     

    LinkedList源碼分析

     LinkedList類似C語言的雙向鏈表,但是java中沒有指針如何實現呢,看完LinkedList
      你將對java中的引用類型有更深入的理解。LindedList的聲明如下:
      public class LinkedList extends AbstractSequentialList implements List, Cloneable, java.io.Serializable
      有關AbstractSequentialList:http://blog.csdn.net/treeroot/archive/2004/09/18/108696.aspx
      有關List: http://blog.csdn.net/treeroot/archive/2004/09/14/104638.aspx
      有關Cloneable:http://blog.csdn.net/treeroot/archive/2004/09/07/96936.aspx
      下面分析一下這個鏈表的實現,這里只重點分析某些方法。
      private transient Entry header = new Entry(null, null, null);
      private transient int size = 0;
      public LinkedList() {
      header.next = header.previous = header;
      }
      header相當于C中的頭指針,而且這個頭指針不是鏈表的元素,有關Entry將在下面介紹。
      public LinkedList(Collection c) {
      this();
      addAll(c);
      }
      public Object getFirst() {
      if (size==0)
      throw new NoSuchElementException();
       return header.next.element;
      }
      頭指針的下一個元素就是第一個元素
      public Object getLast() {
      if (size==0)
      throw new NoSuchElementException();
      return header.previous.element;
      }
      頭指針的前一個當然就是最后一個了
      public Object removeFirst() {
      Object first = header.next.element;
      remove(header.next);
      return first;
      }
      public Object removeLast() {
      Object last = header.previous.element;
      remove(header.previous);
      return last;
      }
      public void addFirst(Object o) {
      addBefore(o, header.next);
      }
      public void addLast(Object o) {
      addBefore(o, header);
      }
      這個方法在鏈表末尾插入新的元素,功能和add方法一樣,這個方法完全是為了對稱性(因為有addFirst)
      public boolean contains(Object o) {
      return indexOf(o) != -1;
      }
      public int size() {
      return size;
      }
      public boolean add(Object o) {
      addBefore(o, header);
      return true;
      }
      public boolean remove(Object o) {
      if (o==null) {
      for (Entry e = header.next; e != header; e = e.next) {
      if (e.element==null) {
      remove(e);
      return true;
      }
      }
      } else {
      for (Entry e = header.next; e != header; e = e.next) {
      if (o.equals(e.element)) {
      remove(e);
      return true;
      }
      }
      }
      return false;
      }
      用過C的人應該感到很熟悉了,這里就是通過指針后移來查找相同的元素,注意這里最多只刪除一個
      元素,符合List接口中的說明。
      public boolean addAll(Collection c) {
      return addAll(size, c);
      }
      public boolean addAll(int index, Collection c) {
      int numNew = c.size();
      if (numNew==0)
      return false;
      modCount++;
      Entry successor = (index==size ? header : entry(index));
      Entry predecessor = successor.previous;
      Iterator it = c.iterator();
      for (int i=0; i
           Entry e = new Entry(it.next(), successor, predecessor);
      predecessor.next = e;
      predecessor = e;
      }
      successor.previous = predecessor;
      size += numNew;
      return true;
      }
      這里又看到熟悉的面孔了,在數據結構里面的鏈表中插入元素不就是這樣嗎?
      successor代表后一個指針,就是說插入的數據在他的前面,predecessor代表前一個指針,也就是要插入數據之前的指針。如果對數據結構比較了解的話,應該比較容易理解,這里我可以把代碼改一下,但是不能算是優化:
      for (int i=0; i
           Entry e = new Entry(it.next(), null, predecessor);
      predecessor.next = e;
      predecessor = e;
      }
      predecessor.next = successor; 
      successor.previous = predecessor;
      這樣修改和原來是一樣的,如果Entry有一個這樣的構造函數Entry(Object element,Entry previous)那就
      好了,那就可以用修改后的代碼優化了(并沒有多大的價值)。如果可以看明白為什么可以這樣修改,那就完全理解了,如果對這種數據結構不熟悉的話,可以畫一個鏈表,然后按代碼執行修改你的鏈表,這個方法很有效的。
      public void clear() {
      modCount++;
      header.next = header.previous = header;
      size = 0;
      }
      public Object get(int index) {
      return entry(index).element;
      }
      public Object set(int index, Object element) {
      Entry e = entry(index);
      Object oldVal = e.element;
      e.element = element;
      return oldVal;
      }
      public void add(int index, Object element) {
      addBefore(element, (index==size ? header : entry(index)));
      }
      public Object remove(int index) {
      Entry e = entry(index);
      remove(e);
      return e.element;
      }
      private Entry entry(int index) {
      if (index < 0 || index >= size)
      throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
      Entry e = header;
      if (index < (size >> 1)) {
      for (int i = 0; i <= index; i++)
      e = e.next;
      } else {
      for (int i = size; i > index; i--)
      e = e.previous;
      }
      return e;
      }
      這個方法返回一個Entry,這里注意注意當index為0時返回的是head.next,不可能返回head。因為index>=0而且
       所以循環語句至少要執行一次。這里指針移動進行了優化,因為是一個雙向鏈表,可以朝不同方向移動,size>>2相當于size=size/2
      public int indexOf(Object o) {
      int index = 0;
      if (o==null) {
      for (Entry e = header.next; e != header; e = e.next) {
      if (e.element==null)
      return index;
      index++;
      }
      } else {
      for (Entry e = header.next; e != header; e = e.next) {
      if (o.equals(e.element))
      return index;
      index++;
      }
      }
      return -1;
      }
      這里唯一注意的就是index++的位置
      public int lastIndexOf(Object o) {
      int index = size;
      if (o==null) {
      for (Entry e = header.previous; e != header; e = e.previous) {
      index--;
      if (e.element==null)
      return index;
      }
      } else {
      for (Entry e = header.previous; e != header; e = e.previous) {
      index--;
      if (o.equals(e.element))
      return index;
      }
      }
      return -1;
      }
      注意index--的位置
      public ListIterator listIterator(int index) {
      return new ListItr(index);
      }
      以下是一個私有內部類
      private class ListItr implements ListIterator {
      private Entry lastReturned = header;
      private Entry next;
      //調用next()方法的節點
      private int nextIndex;
      private int expectedModCount = modCount;
      ListItr(int index) {
      if (index < 0 || index > size)
      throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
      if (index < (size >> 1)) {
      next = header.next;
      for (nextIndex=0; nextIndex
               next = next.next;
      } else {
      next = header;
      for (nextIndex=size; nextIndex>index; nextIndex--)
      next = next.previous;
      }
      }
      public boolean hasNext() {
      return nextIndex != size;
      }
      public Object next() {
      checkForComodification();
      if (nextIndex == size)
      throw new NoSuchElementException();
       lastReturned = next;
      next = next.next;
      nextIndex++;
      return lastReturned.element;
      }
      public boolean hasPrevious() {
      return nextIndex != 0;
      }
      public Object previous() {
      if (nextIndex == 0)
      throw new NoSuchElementException();
        lastReturned = next = next.previous;
      nextIndex--;
      checkForComodification();
      return lastReturned.element;
      }
      public int nextIndex() {
      return nextIndex;
      }
      public int previousIndex() {
      return nextIndex-1;
      }
      public void remove() {
      checkForComodification();
      try {
      LinkedList.this.remove(lastReturned);
      } catch (NoSuchElementException e) {
      throw new IllegalStateException();
      }
      if (next==lastReturned)  //這里表示刪除的是調用previous()返回的元素。
      next = lastReturned.next; //next被刪除,所以next要后移,索引不變。
      else
      nextIndex--;      //刪除的是next.previous,所以索引要減1。     
      lastReturned = header;  //這里很重要:1.釋放資源。2.不允許連續調用remove。
      expectedModCount++;
      }
      public void set(Object o) {
      if (lastReturned == header)
      throw new IllegalStateException();
      checkForComodification();
      lastReturned.element = o;
      }
      public void add(Object o) {
      checkForComodification();
      lastReturned = header;
      addBefore(o, next);
      nextIndex++;
      expectedModCount++;
      }
      final void checkForComodification() {
      if (modCount != expectedModCount)
      throw new ConcurrentModificationException();
      }
      }
      以下是Entry的定義:
      private static class Entry {
      Object element;
      Entry next;
      Entry previous;
      Entry(Object element, Entry next, Entry previous) {
      this.element = element;
      this.next = next;
      this.previous = previous;
      }
      }
      很簡單,就是一個雙向鏈表的接點,只有一個構造函數而已,沒有其他方法。這里的next和previous不就是一個引用嗎?其實不就是一個C里面的指針嗎!不過C語言不會處理空指針,直接讓操作系統處理了,Java確實拋出一個系統異常NullPointerException,根本不給他破壞系統的機會。
      private Entry addBefore(Object o, Entry e) {
      Entry newEntry = new Entry(o, e, e.previous);
      newEntry.previous.next = newEntry;
      newEntry.next.previous = newEntry;
      size++;
      modCount++;
      return newEntry;
      }
      private void remove(Entry e) {
      if (e == header)
      throw new NoSuchElementException();
       e.previous.next = e.next;
      e.next.previous = e.previous;
      size--;
      modCount++;
      }
      public Object clone() {
      LinkedList clone = null;
      try {
      clone = (LinkedList)super.clone();
      } catch (CloneNotSupportedException e) {
      throw new InternalError();
      }
      // Put clone into "virgin" state
      clone.header = new Entry(null, null, null);
      clone.header.next = clone.header.previous = clone.header;
      clone.size = 0;
      clone.modCount = 0;
      // Initialize clone with our elements
      for (Entry e = header.next; e != header; e = e.next)
      clone.add(e.element);
       return clone;
      }
      public Object[] toArray() {
      Object[] result = new Object[size];
      int i = 0;
      for (Entry e = header.next; e != header; e = e.next)
      result[i++] = e.element;
      return result;
      }
      }
      public Object[] toArray(Object a[]) {
      if (a.length < size)
      a = (Object[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
      int i = 0;
      for (Entry e = header.next; e != header; e = e.next)
      a[i++] = e.element;
       if (a.length > size)
      a[size] = null;
       return a;
      }
      private static final long serialVersionUID = 876323262645176354L;
      private synchronized 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 (Entry e = header.next; e != header; e = e.next)
      s.writeObject(e.element);
      }
      private synchronized 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();
      // Initialize header
      header = new Entry(null, null, null);
      header.next = header.previous = header;
      // Read in all elements in the proper order.
      for (int i=0; i
           add(s.readObject());
      }
      這里和ArrayList有一個區別就是size被聲明為 transient的,因為這里調用的是add方法,這樣
      size會自動增加,而在ArrayList是直接給數組賦值(效率更高)。
      這里比較一下ArrayList和LinkedList:
      1.ArrayList是基于數組,LinkedList基于鏈表實現。
      2.對于隨機訪問get和set,ArrayList覺得優于LinkedList,因為LinkedList要移動指針。
      3.對于新增和刪除操作add和remove,LinedList比較占優勢,因為ArrayList要移動數據。
      4.查找操作indexOf,lastIndexOf,contains等,兩者差不多。
      這里只是理論上分析,事實上也不一定,比如ArrayList在末尾插入和刪除數據就不設計到數據移動,不過還是
      有這么個建議:隨機訪問比較多的話一定要用ArrayList而不是LinkedList,如果需要頻繁的插入和刪除應該
      考慮用LinkedList來提高性能。
    引自:http://www.wangchao.net.cn/bbsshowlist.jsp?area_id=02&board_id=01&parent_id=43264

    posted on 2006-03-29 21:01 chenhui 閱讀(933) 評論(0)  編輯  收藏 所屬分類: 好文收集

    導航

    統計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    介紹 IOC

    友情鏈接

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 精品国产亚洲一区二区三区| 免费人成动漫在线播放r18| 亚洲精品在线视频| 在线观看无码AV网站永久免费| 国产色爽免费无码视频| 福利片免费一区二区三区| 亚洲一区二区三区四区视频| 亚洲AV日韩AV永久无码免下载| 亚洲国产精品成人| 国产女高清在线看免费观看| 一个人看www在线高清免费看 | 日韩免费无砖专区2020狼| 免费视频专区一国产盗摄| 99热这里只有精品免费播放| 91视频免费网站| 一级**爱片免费视频| 黄页视频在线观看免费| 无码色偷偷亚洲国内自拍| 亚洲一区二区无码偷拍| 中中文字幕亚洲无线码| 亚洲一级毛片中文字幕| 亚洲男人的天堂在线| 亚洲沟沟美女亚洲沟沟| 亚洲精品91在线| 亚洲国产超清无码专区| 亚洲理论片中文字幕电影| 亚洲经典在线观看| 亚洲精品无码久久毛片波多野吉衣| 亚洲AV无码专区电影在线观看| 久久亚洲色一区二区三区| 国产AV无码专区亚洲AWWW| 亚洲乱码中文字幕久久孕妇黑人| 久久久久亚洲精品天堂久久久久久| 亚洲国产成人精品女人久久久 | 亚洲欧洲自拍拍偷精品 美利坚| heyzo亚洲精品日韩| 亚洲精品无码久久不卡| 久久亚洲AV无码西西人体| 国产精品亚洲片在线观看不卡 | 最近2019免费中文字幕视频三| 最近2019中文字幕免费大全5|