天天看點

資料結構之--單連結清單MyArrayList

仿照Java集合類庫中的ArrayList,自己手動寫了一個MyArrayList,内部使用一個數組來維護。具體的adt描述如下

isEmpty()    判斷是否為空

size()      擷取目前存儲的元素個數

clear()     清空目前的所有元素

set(idx, e)    重置指定位置的元素

ensureCapacity(newCapacity)  指定底層數組的大小

add(e)      添加一個元素,預設在尾部

add(idx, e)    在指定位置添加一個元素

remove(idx)    删除指定位置的元素

iterator()      傳回相應的疊代器

1 /**
  2  * 手寫的一個MyArraylist實作ArrayList的正常操作,并且也實作了疊代器
  3  * 實作疊代器操作,必須要實作Iteratable接口
  4  * @author Administrator
  5  *
  6  * @param <AnyType> 手寫的這個順序表支援泛型
  7  */
  8 public class MyArrayList<AnyType> implements Iterable<AnyType>{
  9     private static final int DEFAULT_CAPACITY = 10;    //預設的 大小為 10
 10     
 11     private int thisSize ;    // 目前已經存入的元素的個數
 12     private AnyType[] theItems;    //定義一個數組用來存儲元素, 而且是一種懶漢模式來維護的
 13     
 14     public MyArrayList(){
 15         clear();
 16     }
 17     
 18     /**
 19      * 清空這個連結清單
 20      */
 21     public void clear()
 22     {
 23         thisSize = 0;
 24         ensureCapacity(DEFAULT_CAPACITY);
 25     }
 26     
 27     public int size(){
 28         return thisSize;
 29     }
 30     public boolean isEmpty()
 31     {
 32         return size()==0;    // 當thisSize==0說明為空連結清單
 33     }
 34     public void trimToSize()
 35     {
 36         ensureCapacity(size());
 37     }
 38     
 39     public AnyType get(int idx)
 40     {
 41         if(idx < 0 || idx >= size())
 42             throw new ArrayIndexOutOfBoundsException();    //    抛出數組越界的異常
 43         return theItems[ idx ];
 44     }
 45     /*
 46      * 重置指定位置idx處的元素 為 newVal
 47      */
 48     public AnyType set(int idx, AnyType newVal)
 49     {
 50         if(idx <= 0 || idx >= size())
 51             throw new ArrayIndexOutOfBoundsException();
 52         AnyType old = theItems[ idx ];
 53         theItems[idx] = newVal;
 54         return old;
 55     }
 56     
 57     public void ensureCapacity( int newCapacity )
 58     {
 59         if(newCapacity < thisSize)// 不需要 修改數組的大小
 60             return ;
 61         
 62         AnyType[] old = theItems;    //先把原來的數組記錄下來
 63 //        theItems = new AnyType[newCapacity]; 注意了 不能這樣建立一個泛型的數組 向下面那樣操作就行了
 64         theItems = (AnyType[]) new Object[ newCapacity ];
 65         for (int i = 0; i < size(); i++) {
 66             theItems[i] = old[i];
 67         }
 68     }
 69     
 70     // 預設在尾部插入
 71     public boolean add(AnyType x)
 72     {
 73         add(size(), x);
 74         return true;
 75     }
 76     
 77     public void add(int idx, AnyType x)
 78     {
 79         if(theItems.length == size())
 80             ensureCapacity(size()*2 + 1);    //一旦size不夠 就擴容兩倍
 81         // 先把 [idx, size]的元素向後移動
 82         for(int i = thisSize; i > idx; i--)// 為什麼 不是 i = thisSieze - 1; 因為初始 thisSize=0的時候 會出現數組越界的情況
 83             theItems[i] = theItems[i-1];
 84         theItems[idx] = x;
 85         thisSize ++;
 86     }
 87     
 88     public AnyType remove(int idx)
 89     {
 90         if(idx <= 0 || idx > size())
 91             throw new ArrayIndexOutOfBoundsException();
 92         AnyType removeItem = theItems[idx-1];
 93         // 吧[idx+1, size]元素想做移動1
 94         for(int i = idx-1; i < size(); i++)
 95             theItems[i] = theItems[i+1];
 96         
 97         thisSize --;
 98         return removeItem;
 99     }
100     
101     
102     @Override
103     public Iterator<AnyType> iterator() {
104         return new MyArrayListIterator();
105     }
106     
107     // 内部類的形式 定義一個自己的 疊代器  内部類 可以友善的通路 外部類的 資料成員
108     private class MyArrayListIterator implements Iterator<AnyType>
109     {
110         private int current = 0;
111         
112         @Override
113         public boolean hasNext() {
114             return current < size();
115         }
116 
117         @Override
118         public AnyType next() {
119             if(!hasNext())
120                 throw new NoSuchElementException();
121             
122             return theItems[current++];
123         }
124 
125         @Override
126         public void remove() {
127             MyArrayList.this.remove(--current);    // 建立調用内部類的方法
128         }
129         
130     }
131     
132     public static void main(String[] args) {
133         MyArrayList<Integer> list = new MyArrayList<Integer>();
134         
135         System.out.println(list.isEmpty());
136         System.out.println(list.size());
137         
138         list.add(1);
139         list.add(2);
140         list.add(3);
141         list.add(4);
142         System.out.println(list.isEmpty());
143         System.out.println(list.size());
144         
145         System.out.println(list.remove(2));
146         
147         System.out.println(list.size());
148         
149         Iterator<Integer> it = list.iterator();
150         while(it.hasNext())
151             System.out.print(it.next()+", ");
152         System.out.println();
153     }
154 
155 }      

 line103~line130其實是很有内容的,這裡把ArrayListIterator定義成了一個内部類。

private class ArrayListIterator implements Iterator<AnyType>{

  private int current = 0;

  public boolean hasNext()

  {return current < size()}  //current < MyArrayList.this.size()

  ………………

  public void remove()

  {MyArraylList.this.remove(--current);}  // 為了消除歧義,就不能簡寫了

},

上面其實都是内部類(Internal class),内部類裡面可以直接通路外部類的屬性和方法,其實在内部類中調用外部類的方法和屬性時,實際上應當是帶上外部類的一個引用比如應當是current < MyArrayList.this.size(),内部類的一大好處是允許程式員簡寫成current < size(),簡寫的前提是内部類和外部類沒有回引起歧義的同名方法或者同名屬性,如果會引起歧義時就不能再簡寫了,比如下面的 remove方法,内部類ArrayListIterator和外部類MyArrayList都有這個方法,那麼在内部類總調用外部類的remove方法時,就不能簡寫了,應當寫成MyArrayList.this.remove(--current);

private static class ArrayListIterator implements Iterator<AnyType>{

}

這種定義情況和上一中乍一看差不多,隻是多了一個static關鍵字而已,這時ArrayListIterator就不在是一個内部類,搖身一變成了一個嵌套類(Nest額的 Class)。嵌套類因為是一個static的,隻能通路被嵌套類中的靜态屬性和靜态方法。

轉載于:https://www.cnblogs.com/OliverZhang/p/6596897.html