手写ArrayList【需要包含构造函数(有参和无参)、add(obj)、扩容机制、并发】

基本和ArrayList编写的没有太多差别,除了一些细节的地方,以供参考

/**
 * 手写ArrayList
 * 需要包含构造函数(有参和无参)、add(obj)、扩容机制
 */
public class MyArrayList implements Serializable {

    //判断当前集合类是否被并发修改,即迭代器并发修改的fail-fast机制 就像版本号控制 如果之前保存的值和当前的值不一样返回异常
    private transient int modCount = 0;

    //第一次扩容的容量
    private static final int DEFAULT_CAPCITY = 10;

    //用于初始化空实例List
    private static final Object[] EMPTY_ELEMENT_DATA = {};

    //实际存储的元素 transient:避免序列化
    transient Object[] elementDate;

    //实际List集合大小 从0开始
    private int size;

    public MyArrayList(){
        this.elementDate = EMPTY_ELEMENT_DATA;

    }

    public MyArrayList(int initialCapcity){

        if(initialCapcity>0){
            this.elementDate = new Object[initialCapcity];
        }else if(initialCapcity == 0){
            //初始化 防止空指针异常
            this.elementDate = EMPTY_ELEMENT_DATA;
        }else {
            throw new IllegalArgumentException("参数异常");
        }
    }

    /**
     * 添加元素
     */
    public boolean add(Object e){

        //判断容量
        ensureCapacityInternal(size+1);
        //使用下标赋值 尾部插入
        elementDate[size++] = e;
        return true;
    }

    /**
     * 计算容量+确保容量
     * @param minCapacity
     */
    private void ensureCapacityInternal(int minCapacity){
        //用于并发判断
        modCount++;

        //如果是初次扩容,则使用默认容量
        if(elementDate == EMPTY_ELEMENT_DATA){
            minCapacity = Math.max(DEFAULT_CAPCITY,minCapacity);
        }
        //是否需要扩容,需要的最少容量大于现在数组的长度则要扩容
        if(minCapacity - elementDate.length>0){
            int oldCapactiy = elementDate.length;

            int newCapacity = oldCapactiy + (oldCapactiy>>1);
            //如果新容量小于最小容量 则将最小容量赋值给新的容量
            if(newCapacity - minCapacity < 0){
                newCapacity = minCapacity;
            }

            //创建新数组
            Object [] objects = new Object[newCapacity];

            //将旧的数据复制到新的数组里面
            System.arraycopy(elementDate,0,objects,0,elementDate.length);

            //修改引用
            elementDate = objects;
        }
    }

    /**
     * 通过下标获取对象
     * @return
     */
    public Object get(int index){
        //参数检查
        rangeCheck(index);
        return elementDate[index];
    }

    private void rangeCheck(int index){
        if(index > size || size < 0 ){
            throw new IndexOutOfBoundsException("数组越界");
        }
    }

    /**
     * 通过对象获取下标位置
     * @param o
     * @return
     */
    public int indexOf(Object o){
        if(o == null){
            for (int i=0;i < size;i++){
                if(elementDate[i]==null){
                    return i;
                }
            }
        }else {
            for (int i=0;i < size;i++){
                if(o.equals(elementDate[i])){
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 更新下标元素
     * @param index
     * @param obj
     * @return
     */
    public Object set(int index,Object obj){
        rangeCheck(index);

        //拿去旧下标
        Object oldValue = elementDate[index];
        //替换
        elementDate[index] = obj;

        return oldValue;
    }

    /**
     * 根据下标删除元素
     * @return
     */
    public Object remove(int index){
        rangeCheck(index);
        //用于并发判断
        modCount++;

        //获取旧元素
        Object oldValue = elementDate[index];
        //后面元素进行移动 计算删除位后面的元素个数
        int numMoved = size - index - 1;
        if (numMoved > 0){
            //当前数组 从当前下标之后 拷贝到也就是覆盖当前数据 从当前下标
            System.arraycopy(elementDate,index+1,elementDate,index,numMoved);
        }
        //最后一个元素进行置空 将多出的位置为空,没有应用对象 垃圾收集器就可以回收 如果不置空 就会保存应用
        //可能造成内存泄漏
        elementDate[--size] = null;
        return oldValue;
    }

    /**
     * 获取数组实际大小
     * @return
     */
    public int size(){
        return this.size;
    }

测试

public class Test {

    public static void main(String [] args){

        MyArrayList list = new MyArrayList();

        //添加
        for (int i = 0; i<10 ; i++){
            list.add(i);
        }

        //遍历
        for (int i = 0 ; i<list.size();i++){
            System.out.println(list.get(i));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/q736317048/article/details/113886970