仿照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手写的这个顺序表支持泛型 7 */ 8 public class MyArrayList implements Iterable { 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 @Override103 public Iterator iterator() {104 return new MyArrayListIterator();105 }106 107 // 内部类的形式 定义一个自己的 迭代器 内部类 可以方便的访问 外部类的 数据成员108 private class MyArrayListIterator implements Iterator 109 {110 private int current = 0;111 112 @Override113 public boolean hasNext() {114 return current < size();115 }116 117 @Override118 public AnyType next() {119 if(!hasNext())120 throw new NoSuchElementException();121 122 return theItems[current++];123 }124 125 @Override126 public void remove() {127 MyArrayList.this.remove(--current); // 创建调用内部类的方法128 }129 130 }131 132 public static void main(String[] args) {133 MyArrayList list = new MyArrayList ();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 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的,只能访问被嵌套类中的静态属性和静态方法。