美文网首页
【Java基础】自己实现一个ArrayList容器

【Java基础】自己实现一个ArrayList容器

作者: 灰色孤星 | 来源:发表于2018-10-07 10:32 被阅读0次

源代码:https://gitee.com/AgentXiao/Collection

10月7日,国庆假期即将过去,秋招又一次高潮即将来临,为了更好地准备,复习一下容器的使用。

一、List

List的三个常用子类:
1、ArrayList:底层实现是数组,线程不安全,效率高;查询快,修改、插入、删除慢。
2、LinkedList:底层实现是链表,线程不安全,效率高。查询慢,修改、插入、删除快。
3、Vector:线程安全的,效率低。

二、自己实现一个MyArrayList

1、首先明确,ArrayList的底层是一个Object[],用int size作为计量容器中对象个数的变量。

    private Object[] elementDate; //对象数组
    private int size;  //容器中的对象个数

2、构造器:当实例化一个ArrayList时,默认创建一个容量为10的Object数组。需要注意,构造器应该是两个,一个有参一个无参,无参默认为10,有参可以指定容量大小。

    //无参构造,默认容量为0
    public MyArrayList() {
        this(10);
    }

    //有参构造,指定容量
    public MyArrayList(int initialCapacity) {
        if(initialCapacity > 0){
            elementDate = new Object[initialCapacity];
        }else if(initialCapacity == 0){
            elementDate= new Object[]{};
        }else{
            throw new RuntimeException("不能构造容量小于0的容器!");
        }
    }

3、增加方法add(Object obj):向容器中增加一个对象。首先需要考虑的问题是,空间是否足够?
如果空间足够,直接赋值即可;如果空间不够,则需要进行扩容ensureCapacity。扩容的三个步骤:扩容 -> 拷贝 -> 替换

    //确保容量足够
    private void ensureCapacity(){
        //如果数组内的对象已达到最大值
        if(size == elementDate.length){
            //扩容:size*2+1
            Object[] newElementDate = new Object[size*2+1];
            //拷贝:将旧数组的内容拷贝到新数组
            System.arraycopy(elementDate,0,newElementDate,0,elementDate.length);
            //替换:旧数组替换为新数组
            elementDate = newElementDate;
        }
    }
    /**
     * @MethodName add
     * @Descrition 添加对象
     * @Param [obj]
     * @return void
     */
    public void add(Object obj){
        ensureCapacity();
        elementDate[size++] = obj;
    }

4、获取长度size()

    /**
     * @MethodName size
     * @Descrition 返回数组中对象的个数
     * @Param []
     * @return int
     */
    public int size(){
        return size;
    }

5、isEmpty()

    /**
     * @MethodName isEmpty
     * @Descrition 判断数组中对象个数是否为0
     * @Param []
     * @return boolean
     */
    public boolean isEmpty(){
        return size == 0;
    }

6、增加方法2:add(int index,Object obj)。在指定的索引位置插入指定的对象
(1)首先考虑索引值是否符合输入规范,封装一个范围检测方法

    /**
     * @MethodName rangeCheck
     * @Descrition 索引检测
     * @Param [index]
     * @return void
     */
    private void rangeCheck(int index){
        if(index >= size){
            throw new RuntimeException("你输入的索引值不在范围之内!");
        }
    }

(2)其次判断是否需要扩容ensureCapacity()
(3)最后进行插入(拷贝 -> 赋值)特别需要注意移动的位数

/**
     * @MethodName add
     * @Descrition 在指定的位置插入对象
     * @Param [index, obj]
     * @return void
     */
    public void add(int index,Object obj){
        rangeCheck(index);
        ensureCapacity();
        //拷贝:相当于集体往后移动
        System.arraycopy(elementDate,index,elementDate,index+1,size-index);
        //赋值
        elementDate[index] = obj;
        size++;
    }

7、获取对象方法get(int index)
(1)索引值判断
(2)获取

    /**
     * @MethodName get
     * @Descrition 获取指定索引对象
     * @Param [index]
     * @return java.lang.Object
     */
    public Object get(int index){
        rangeCheck(index);
        return elementDate[index];
    }

8、移除方法1:remove(int index)
(1)拷贝(往前移)
(2)将最后一个对象赋值为null
一定要搞清楚变量的变化,最好举个例子进行模拟

    /**
     * @MethodName remove
     * @Descrition 移除指定索引位置的对象
     * @Param [index]
     * @return void
     */
    public void remove(int index){
        rangeCheck(index);
        //拷贝(往前移)
        int numMoved = size - index - 1;
        if(numMoved > 0){
            System.arraycopy(elementDate,index+1,elementDate,index,numMoved);
        }
        //赋值
        size--;
        elementDate[size] = null;
    }

9、移除方法2:remove(Object obj)
(1)这里需要特别注意的是,底层使用equals判断是那个对象

    /**
     * @MethodName remove
     * @Descrition 移除指定的对象
     * @Param [obj]
     * @return void
     */
    public void remove(Object obj){
        for(int i=0;i<size;i++){
            if(elementDate[i].equals(obj)){  //注意:底层使用的equals
                remove(i);
            }
        }
    }

10、替换方法set(int index,Object obj)
(1)判断所引致规范
(2)替换

    /**
     * @MethodName set
     * @Descrition 替换指定位置的对象
     * @Param [index, obj]
     * @return java.lang.Object
     */
    public Object set(int index,Object obj){
        rangeCheck(index);
        Object oldElement = elementDate[index];
        elementDate[index] = obj;
        return oldElement;
    }

相关文章

网友评论

      本文标题:【Java基础】自己实现一个ArrayList容器

      本文链接:https://www.haomeiwen.com/subject/qpwkaftx.html