Java底层之ArrayList底层实现原理

ArrayList简介

    ArrayList就是动态数组,,相当于Array的复杂版本,它提供了动态的增加和减少元素,实现了Collection和List接口,可以灵活的设置数组的大小。要注意的是ArrayList并不是线程安全的,因此一般建议在单线程中使用ArrayList。ArrayList的元素可以为null;

源码解析

    ArrayList底层使用数组存储元素,默认数组大小为10

//默认数组大小
private static final int DEFAULT_CAPACITY = 10;
//定义存储数组
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

  1. indexOf(Object o)方法 

    //查找某个元素,返回找到的第一个的下标
    public int indexOf(Object o) {
        //如果查找null,返回元素为null的下标
        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;
        }
        //查询不到返回-1
        return -1;
    }

  2. lastIndexOf(Object o)方法 

    //查找元素,返回找到的最后一个元素的下标,方法同indexOf相似
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            //倒叙遍历数组,indexOf为正序
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

  3. get(int index)方法 

    //根据下标获取数组元素
    public E get(int index) {
        //检查索引是否越界
        rangeCheck(index);
        //返回下标所在的元素
        return elementData(index);
    }
    private void rangeCheck(int index) {
        //如果索引大于数组长度,抛出索引越界异常
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

   4. add(E e)方法:当数组容量不够时,扩容为原来的1.5倍

    //添加元素
    public boolean add(E e) {
        //在加入元素前,检查数组容量是否足够
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        //判断现在的ArrayList是不是空的,如果是空的,minCapacity就取默认的容量和传入的参数minCapacity中的大值
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //判断是否需要扩容
        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
         // 添加一个元素后的长度大于数组长度时,进行扩容(只有在数组为空的时候,minCapacity为默认容量和传入参数的最大值,其余时候为当前数组元素个数+1)
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        //原数组长度
        int oldCapacity = elementData.length;
        //扩容后的容量为原容量+原容量/2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 数组复制
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

   4. set(int index, E element)方法 :替换掉原位置的元素

    public E set(int index, E element) {
        //检查index是否超出数组索引范围
        rangeCheck(index);
        E oldValue = elementData(index);
        // 替换掉原位置的元素
        elementData[index] = element;
        return oldValue;
    }
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

   5. add(int index, E element)方法 :插入元素,后边的元素后移

   public void add(int index, E element) {
        //检查索引是否越界,同上
        rangeCheckForAdd(index);
        //检查数组容量是否足够
        ensureCapacityInternal(size + 1);
        //进行数组插入位置后的元素复制,后移一位
        System.arraycopy(elementData, index, elementData, index + 1,
            size - index);
        //插入元素
        elementData[index] = element;
        size++;
    }

   6. remove(int index)方法 

    public E remove(int index) {
        //检查索引是否越界
        rangeCheck(index);
        modCount++;
        E oldValue = elementData(index);
        //删除元素后,需要移动的元素个数,即多少元素需要前移一位
        int numMoved = size - index - 1;
        if (numMoved > 0)
            //数组复制后迁移一位,待删除元素被覆盖
            System.arraycopy(elementData, index+1, elementData, index,
                numMoved);
        //最后空出来的位置赋值null
        elementData[--size] = null;
        return oldValue;
    }

 

你可能感兴趣的:(Java基础,知识点)