模仿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倒是相差无几。

posted @ 2019-04-09 11:18  砖厂繁忙在下告辞  阅读(189)  评论(0编辑  收藏  举报