手写ArrayList集合框架

Posted suyang-java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写ArrayList集合框架相关的知识,希望对你有一定的参考价值。

    List集合是我们平时常用的集合框架,List集合是有序的,在java中List接口主要有两个实现分别是ArrayList和LinkedList,其中ArrayList类主要是通过数组的方式实现的。因为ArrayList底层是通过数组的方式实现List集合,所以在访问集合中的数据时可以直接通过数组的下标访问,效率较高。由于在java中数组的大小必须在定义数组时确定并且不能修改,所以在对ArrayList集合添加和删除时需要考虑是否需要对数组扩容同时移动数组下标。

    下面是我自己实现的List集合的代码:

     1.首先我要定义一个List接口:

public interface List<E> {
    //返回此列表中的元素数。
    int size();
    //如果此列表不包含元素,则返回 true 。
    boolean isEmpty();
    //如果此列表包含指定的元素,则返回 true 。
    boolean contains(Object o);
    //将指定的项目添加到滚动列表的末尾。
    boolean add(E e);
    //从列表中删除指定元素的第一个出现(如果存在)。
    boolean remove(Object o);
    //返回此列表中指定位置的元素。
    E get(int index);
    //用指定的元素替换此列表中指定位置的元素。
    E set(int index, E element);
    //在此列表中的指定位置插入指定的元素。
    void add(int index, E element);
    //删除该列表中指定位置的元素。
    E remove(int index);
    //返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
    int indexOf(Object o);
    //返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。 更正式地,返回最高指数i ,使得(o==null ? get(i)==null : o.equals(get(i))) ,或-1如果没有这样的索引。
    int lastIndexOf(Object o);

}

然后再定义一个ListArray类来实现这个List接口。

public class ListArray<E> implements List<E> {

    private static final int DEFAULT_CAPACITY = 10;
    private int size;
    private Object[] elementData;


    public ListArray() {
        this.elementData = new Object[DEFAULT_CAPACITY];
    }

    public ListArray(int initialCapacity){
        if(initialCapacity>0){
            this.elementData = new Object[initialCapacity];
        }else{
            this.elementData = new Object[DEFAULT_CAPACITY];
        }
    }



    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size==0;
    }

    @Override
    public boolean contains(Object o) {
        boolean flag = false;
        if(elementData.length>0){
            for(int i=0;i<elementData.length;i++){
                if(elementData[i].equals(o)){
                    flag=true;
                    break;
                }
            }
        }
        return flag;
    }

    @Override
    public boolean add(E e) {
        checkNeedExtends(size+1);
        this.elementData[size] = e;
        size++;
        return true;
    }



    @Override
    public boolean remove(Object o) {
        E e = remove(indexOf(o));
        return e!=null;
    }

    @Override
    public E get(int index) {
        return (E)elementData[index];
    }

    @Override
    public E set(int index, E element) {
        checkIndex(index);
        elementData[index] =element;
        return element;
    }

    @Override
    public void add(int index, E element) {
        checkNeedExtends(size+1);
        checkIndex(index);
        for(int j=size;j>index;j--){
            elementData[j] = elementData[j-1];
        }
        elementData[index] = element;
        size++;

    }

    private void checkIndex(int index) {
        if(index<0||index>elementData.length-1){
            throw new RuntimeException("索引越界");
        }
    }

    @Override
    public E remove(int index) {
        checkIndex(index);
        if(size==0){
            return null;
        }else{
           E result = get(index);
           for(int j=size-1;j>index;index++){
                elementData[index] = elementData[index+1];
           }
           elementData[size-1] = null;
           size--;
           return result;

        }

    }

    @Override
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    @Override
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    private void checkNeedExtends(int minCapacity) {
        if(elementData.length - minCapacity<0){
            grow();
        }
    }

    private void grow() {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        Object[] newEle = new Object[newCapacity];
        for(int i=0;i<size;i++){
            newEle[i] = elementData[i];
        }
        elementData = newEle;
    }
    
}

这里DEFAULT_CAPACITY表示集合框架的初始容量,elementData表示用来存储数据的数组,size表示线性表的长度。通过代码我们知道在一个具有n个数据元素的数组插入和删除一个数据元素的时间复杂度为O(n),查询的时间复杂度为O(1)。所以ArrayList适用于查询不适用于添加和修改。

 

以上是关于手写ArrayList集合框架的主要内容,如果未能解决你的问题,请参考以下文章

JavaLearn#(15)集合提升训练:手写ArrayList单链表LinkedListHashMapHashSet新一代并发集合类

手写集合框架LinkedList实现篇

面试必会之ArrayList源码分析&手写ArrayList

Java自学-集合框架 ArrayList和HashSet的区别

集合框架之ArrayList集合

1 手写ArrayList核心源码