ArrayList深入解析源码

1.add()

 public boolean add(E e) {
        //1.判断是否需要扩容
        //2.进行扩容
        //size+1:因为添加了一个元素所以要加1
        ensureCapacityInternal(size + 1);  // Increments modCount!!

        //对扩容完的data进行添加数据
        //size++:因为添加了一个元素所以要加1
        elementData[size++] = e;

        //前面没有问题表示添加成功返回true
        return true;
    }

    /**
     * 扩容方法
     * @param minCapacity 最小扩容大小
     */
    private void ensureCapacityInternal(int minCapacity) {
        //1.对比判断最小扩容大小,默认最小10
        //2.进行扩容
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    /**
     * 扩容判断
     * @param elementData 数据
     * @param minCapacity 最小扩容大小
     * @return 最小扩容大小
     */
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //如果当前的数据为空DEFAULTCAPACITY_EMPTY_ELEMENTDATA={},则最小扩容大小和默认最小10容量比较找出大的
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //返回最小扩容大小
        return minCapacity;
    }

    /**
     * 扩容判断
     * @param minCapacity 最小扩容大小
     */
    private void ensureExplicitCapacity(int minCapacity) {
        //修改操作数加1
        modCount++;

        // 如果需要扩容的容量>数据的长度进行扩容,否则不需进行扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    /**
     * 最终扩容方法
     * @param minCapacity 最小扩容大小
     */
    private void grow(int minCapacity) {
        // 原来的容等于数据长度
        int oldCapacity = elementData.length;
        //新容量等于原来容量*3/2,也就是原来的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //如果新容量<最小扩容大小则容量扩容为最小扩容大小也就是默认10或者size+1
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //如果新容量>最大数组容量(Integer.MAX_VALUE-8)
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            //最大容量判断
            newCapacity = hugeCapacity(minCapacity);
        //扩容完之后进行数据拷贝,把原来的数据拷贝到扩容后的数组里
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    /**
     * 扩容判断
     * @param minCapacity 最小扩容大小
     * @return 最大容量
     */
    private static int hugeCapacity(int minCapacity) {
        //如果容量已经超过int的最大限度,抛出异常
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        //如果最小扩容大小>数组最大容量(Integer.MAX_VALUE-8)返回Integer.MAX否则等于Integer.MAX_VALUE-8
        return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }

总结:在添加数据的时候,需先进行扩容判断,如果容量不够则进行扩容。容量扩容成原来数据长度的1.5倍,初始化容量默认最小为10,最大容量为Integer.MAX_VALUE。

2.addAll()

public boolean addAll(Collection<? extends E> c) {
        //转化成数组
        Object[] a = c.toArray();
        //获取数据长度
        int numNew = a.length;
        //原有的数据长度+添加的数据长度进行扩容
        ensureCapacityInternal(size + numNew);  // Increments modCount
        //扩容完进行数据拷贝,拷贝到扩容后的数组里
        System.arraycopy(a, 0, elementData, size, numNew);
        //现在数据长度=原有的数据长度+添加的数据长度
        size += numNew;
        //如果添加的数据长度不为0返回true,否则false
        return numNew != 0;
    }

3.get()

public E get(int index) {
        //检查是否越界
        rangeCheck(index);
        //返回下标数据
        return elementData(index);
    }

    private void rangeCheck(int index) {
        //如果查找的下标大于数据长度,抛出异常
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    

总结:获取的时候,需要检查下标是否越界,没有返回对应下标的数据。

4.remove()

   public E remove(int index) {
        //检查数组是否越界,越界抛出异常
        rangeCheck(index);
        //操作数++
        modCount++;
        //获取数据
        E oldValue = elementData(index);
        //拷贝数据的长度
        int numMoved = size - index - 1;
        //如果需要拷贝数据
        if (numMoved > 0)
            //1.目标数据elementData,2.要从哪个地方开始拷贝index+1,3.拷贝的长度numMoved,4.数据拷贝到这个对象(第3个elementData),5.目标数组的开始拷贝起始位置index
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        //把最后的数据置空,并长度减1
        elementData[--size] = null; // clear to let GC do its work
        //返回删除的数据
        return oldValue;
    }

移除图解(图片来自小博哥)

总结:删除的时候,判断是否下标越界,先进行数据拷贝,然后把最后的数据置为空、长度减1。

猜你喜欢

转载自blog.csdn.net/ysfengshu/article/details/126994445