模仿ArrayList和它的Iterator
package cn.yangwanhao.collection.list; import java.util.Iterator; import java.util.NoSuchElementException; /** * Title: MyArrayList类<br> * Description: 模仿ArrayList和Iterator * Company: 卓瀛工作室 * * @author 杨万浩 * @version 1.0 */ public class MyArrayList<E> implements Iterable<E> { /** * 初始化数组容量为10 */ private static final int DEFAULT_CAPACITY = 10; /** * 集合的长度 */ private int theSize; /** * 集合体 */ private E [] theItems; /** * 构造方法,初始化数组 */ public MyArrayList() { doClear(); } /** * 对外提供的初始化数组的方法 */ public void clear() { doClear(); } /** * 初始化数组的方法 */ private void doClear() { //把数组大小设为0 theSize = 0; ensureCapacity(DEFAULT_CAPACITY); } /** * 提供集合大小的方法 * @return 数组的大小 */ public int size() { return theSize; } /** * 判断集合是否为空 * @return 数组的大小是否为0 */ public boolean isEmpty() { return theSize==0; } /** * 把数组多余的部分切掉 */ public void trimToSize() { ensureCapacity(size()); } /** * 数组扩容 * @param newCapacity 新的数组大小 */ private void ensureCapacity(int newCapacity) { //如果新的容量比现有的容量还小,直接返回 if(newCapacity < theSize) { System.out.println(newCapacity + " < " + theSize); return; } //获取旧的数组体 E [] old = theItems; //新建一个数组 theItems = (E []) new Object[newCapacity]; //把旧的数组copy过去 for(int i=0; i<size(); i++) { theItems[i] = old[i]; } } /** * 获取集合中特定位置的值 * @param idx 值在集合中的位置 * @return 该位置的元素 */ public E get(int idx) { if (idx < 0 || idx >= size()) { throw new ArrayIndexOutOfBoundsException(); } return theItems[idx]; } /** * 修改集合中某个特定位置的元素 * @param idx 要修改的元素在集合中的位置 * @param newVal 要修改的元素的新值 * @return 返回旧的元素(被替换掉的元素)的值 */ public E set(int idx, E newVal) { if(idx < 0 || idx >= size()) { throw new ArrayIndexOutOfBoundsException(); } E old = theItems[idx]; theItems[idx] = newVal; return old; } /** * 添加一个元素到集合尾部 * @param val 要添加的元素 * @return 添加成功 */ public boolean add(E val) { add(size(), val); return true; } /** * 添加元素到指定位置 * @param idx 位置 * @param val 元素的值 */ public void add(int idx ,E val) { //如果数组的容量已经满了,就进行扩容 if(theItems.length == size()) { ensureCapacity(size()+(size()>>1)); } //把idx位置后边的值依次往后挪一位,腾出idx那个位置 for(int i=theSize; i>idx; i--) { theItems[i] = theItems[i-1]; } //赋值 theItems[idx] = val; //集合长度+1 theSize++; } /** * 删除集合中特定位置的一个元素 * @param idx 位置 * @return 删除的那个元素 */ public E remove(int idx) { //得到那个要被删除的元素 E removeItem = theItems[idx]; //把该位置元素之后的元素依次向前挪一位 for (int i=idx; i<size()-1; i++) { theItems[i] = theItems[i+1]; } //集合长度-1 theSize--; return removeItem; } /** * Returns an iterator over elements of type {@code T}. * @return an Iterator. */ @Override public Iterator<E> iterator() { return new MyArrayListIterator(); } private class MyArrayListIterator implements Iterator<E> { private int current = 0; @Override public boolean hasNext() { return current<size(); } @Override public E next() { if(!hasNext()) { throw new NoSuchElementException(); } return theItems[current++]; } @Override public void remove() { MyArrayList.this.remove(--current); } } }
ArrayList底层使用数组完成。创建时初始化一个数组长度。每次执行添加操作时先查询数组里是否还有空间,如果有就添加,如果没有,则进行扩容操作。扩容就是先获取旧的数组,再创建一个新的数组,初始化它的长度为原数组的1.5倍,再把旧数组的内容拷贝过去。由于每次(在表前或者中间)添加或者删除一个元素都需要挪动后边的元素,所以ArrayList的添加或者删除的效率很低。但是数组根据下标来查询或者修改某个特定的元素时时间复杂度为O(1),所以它的查询很快。至于遍历......他们都是从前往后一个一个遍历,和LinkedList倒是相差无几。