重新手动梳理一遍数据结构中的一些例程的实现。首先是ArrayList:
class Test {
public static void main(String[] args) {
MyArrayList<Integer> lst = new MyArrayList<Integer>();
for (int i = 0; i < 10; i++)
lst.add(i);
for (int i = 20; i < 30; i++)
lst.add(0, i);
lst.remove(0);
lst.remove(lst.size() - 1);
System.out.println(lst);
}
}
class MyArrayList<AnyType> implements Iterable<AnyType> {
private static final int DEFAULT = 10;
private int theSize;
private AnyType[] theItems;
public MyArrayList() {
clear(); // 构造方法
}
public void clear() {
theSize = 0;
ensureCapacity(DEFAULT); // 清除同时改变大小
}
public void ensureCapacity(int newCapacity) { // 扩充容量
if (newCapacity < theSize)
return;
AnyType[] old = theItems; // 存储源数组的一个引用
theItems = (AnyType[]) new Object[newCapacity]; // 为新数组分配内存,因不清除类型,引用超类型。(会产生警告,不可避免)
for (int i = 0; i < size(); i++) {
theItems[i] = old[i];
}
}
public int size() {
return theSize;
}
public boolean isEmpty() {
return size() == 0;
}
public void trimToSize() { // 将此ArrayList的实例容量调整为列表的当前大小。
ensureCapacity(size());
}
public AnyType get(int idx) {
if(idx<0 || idx>=size()) throw new ArrayIndexOutOfBoundsException();
return theItems[idx];
}
public AnyType set(int idx, AnyType newVal) { //注意返回类型。
if(idx<0 || idx>=size()) throw new ArrayIndexOutOfBoundsException();
AnyType old = theItems[idx];
theItems[idx] = newVal;
return old; //返回的是位于该位置上元素。
}
public boolean add(AnyType x) { // 添加到表的末端
add(size(),x);
return true;
}
public void add(int idx, AnyType x) { // 添加到指定位置,add方法要求增加容量,如扩充容量,它就要变成原来大小的两倍,以便面不得不再次改变。
if (theItems.length == size())
ensureCapacity(size() * 2 + 1); // +1用来表示防止大小是0的情况。
for (int i = theSize; i > idx; i--) {
theItems[i] = theItems[i - 1];
}
theItems[idx] = x;
theSize++;
}
public AnyType remove(int idx) { // 删除操作,位于指定上或指定位置后的元素向低位移动一个。
AnyType removeItem = theItems[idx];
for (int i = idx; i < size() - 1; i++)
theItems[i] = theItems[i + 1];
theSize--;
return removeItem;
}
public java.util.Iterator<AnyType> iterator() { // 该方法返回一个ArrayListIterator类的一个实例
return new ArrayListIterator();
}
private class ArrayListIterator implements java.util.Iterator<AnyType> { // 存储当前位置,当前位置即要被查看的下一元素(的数组下标)
private int current = 0;
private boolean ok = false;
public boolean hasNext() {
return current < size();
}
public AnyType next() {
if (!hasNext())
throw new java.util.NoSuchElementException();
ok = true;
return theItems[current++];
}
public void remove() {
if (!ok)
throw new IllegalStateException();
MyArrayList.this.remove(--current);
ok = false;
}
}
// 这里说明一下,ArrayListIterator是内部类,private可见性是为了只能让其外部内访问。
// 删除调用的是MyArrayList的remove来实现迭代器的remove方法,原因是避免remove可能与MyArrayList的remove冲突。
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (AnyType x : this)
sb.append(x + " ");
sb.append("]");
return new String(sb);
}
// 这里不得不说一下String,StringBuffer和StringBuilder的区别了,其实说起来挺多,总结起来就是:
// 1)String是不可变的对象,每次对String类型进行改变的时候都等同于生成了一个新的String对象,
// 然后将指针指向新的对象,所以经常改变的字符串最好不要用String,因为每次生成对象都会算上产生一次垃圾,GC收集起来麻烦。
// 2)StringBuffer则是对对象本身进行操作,是可变的。
// 3)StringBuilder是jdk1.5之后新增加的,它是支持单线程的,StringBuffer则可以支持多线程,它可以处理同步问题。
}
OK。搞完了。准备下一个。