JAVA面试题 手写ArrayList的实现,在笔试中过关斩将?

面试官Q1:能够手写一个ArrayList的简单实现吗?面试

咱们都知道ArrayList是基于数组实现,若是让你实现JDK源码ArrayList中add()、remove()、get()方法,你知道如何实现吗?这一节,咱们不看源码,咱们想一想如何简单的实现ArrayList几个基本方法?数组

肯定数据结构数据结构

咱们知道,ArrayList中不管什么数据都能放,是否是意味着它是一个Object类型,既然是数组,那么是否是Object[]数组类型的?因此咱们定义的数据结构以下:性能

private Object[] elementData;  
private int size;
设置自定义的MyArrayList的长度为10

public MyArrayList(){
         this(10);
 }
 
public MyArrayList(int initialCapacity){
      if(initialCapacity<0){
             try {
                 throw new Exception();
             } catch (Exception e) {
                e.printStackTrace();
            }
        }
        elementData = new Object[initialCapacity];
}

有了存放数据的位置,接下来,咱们想一想如何将数据放入数组?this

添加数据spa

public void add(Object obj){
        elementData[size++]=obj;
}

每添加一个元素,size就会自增1,咱们定义的数组长度为10,当咱们添加到11个元素的时候,显然没有地方存放新添加的数据,这个时候咱们须要对数组进行扩容处理对上面代码作以下修改:code

public void add(Object obj){
         if(size==elementData.length){
            //建立一个新的数组,而且这个数组的长度是原数组长度的2倍
             Object[] newArray = new Object[size*2];
            //使用底层拷贝,将原数组的内容拷贝到新数组
             System.arraycopy(elementData, 0, newArray, 0, elementData.length);
            //并将新数组赋值给原数组的引用
             elementData = newArray;
         }
        //新来的元素,直接赋值
        elementData[size++]=obj;
}

用一张图来表示就是这样的:对象

clipboard.png

查询数据blog

public Object get(int index){
        return elementData[index];
}

删除数据索引

接着咱们看一下删除的操做。ArrayList支持两种删除方式:

  • 按照下标删除
  • 按照元素删除,这会删除ArrayList中与指定要删除的元素匹配的第一个元素

对于ArrayList来讲,这两种删除的方法差很少,都是调用的下面一段代码:

public void remove(int index){
         //删除指定位置的对象
         //a b d e
         int numMoved = size - index - 1;
         if (numMoved > 0){
             System.arraycopy(elementData, index+1, elementData, index,
                     numMoved);
         }
         elementData[--size] = null; // Let gc do its work
}

其实作的事情就是两件:

  • 把指定元素后面位置的全部元素,利用System.arraycopy方法总体向前移动一个位置
  • 最后一个位置的元素指定为null,这样让gc能够去回收它

用图表示是这样的:

clipboard.png

指定位置添加数据
把从指定位置开始的全部元素利用System,arraycopy方法作一个总体的复制,向后移动一个位置(固然先要用ensureCapacity方法进行判断,加了一个元素以后数组会不会不够大),而后指定位置的元素设置为须要插入的元素,完成了一次插入的操做。

public void add(int index,Object obj){
        ensureCapacity();  //数组扩容
        System.arraycopy(elementData, index, elementData, index + 1,
                 size - index);
        elementData[index] = obj;
        size++;
}

用图表示这个过程是这样的:

clipboard.png

总结一下
从上面的几个过程总结一下ArrayList的特色:

ArrayList底层以数组实现,是一种随机访问模式,经过下标索引定位数据,因此查找很是快

ArrayList在顺序添加一个元素的时候很是方便,只是往数组里面添加了一个元素而已(这里指的末尾添加数据)

当删除元素的时候,涉及到一次元素复制移位,若是要复制的元素不少,那么就会比较耗费性能

当插入元素的时候,涉及到一次元素复制移位,若是要复制的元素不少,那么就会比较耗费性能

所以,ArrayList比较适合顺序添加、随机访问的场景。

相关文章
相关标签/搜索