美文网首页
ArrayList 源码分析

ArrayList 源码分析

作者: gcno93 | 来源:发表于2021-09-23 03:38 被阅读0次

描述

ArrayList 现实了List接口,是一个顺序容器,存放元素的顺序和取出元素的顺序是一样的,内部是用<mark style="box-sizing: border-box;">数组</mark>来实现的,<mark style="box-sizing: border-box;">可以存放null</mark>

成员属性

private static final int DEFAULT_CAPACITY = 10; //默认容器长度

private static final Object[] EMPTY_ELEMENTDATA = {}; //空数组,也就是new ArrayList(0)

image.png

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //也是空数组 new ArrayList()

[图片上传失败...(image-f94dc8-1632339423811)]

transient Object[] elementData; //真正的用来保存元素的数组

private int size; //元素个数

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //可以分配的最大元素个数

protected transient int modCount = 0; //被这个list内容被修改的次数,比如add,remove() 都会加+1,这个参数也是Fail-Fast机制时使用的,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险

方法

add()

image.png
 private void ensureCapacityInternal(int minCapacity) {
        //这个if 只是在new ArrayList() 之后 add()就会进去
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//默认 10 和1 比,当然是10
        }

        ensureExplicitCapacity(minCapacity);//进去
    }

   private void ensureExplicitCapacity(int minCapacity) {
        modCount++; //发送修改 modCount+1

        // overflow-conscious code
        if (minCapacity - elementData.length > 0) // minCapacity 是否大于原来的容器长度,这个是关键判断
            grow(minCapacity); //扩容全靠它了了,哈哈
    }

  private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length; //保存原容器的长度
        int newCapacity = oldCapacity + (oldCapacity >> 1); //新的容器长度 = 原容器的长度 + 原容器的长度的一半
        if (newCapacity - minCapacity < 0) //新的容器长度是否小于传进来的长度
            newCapacity = minCapacity; //新的容器长度 = 传进来的长度
        if (newCapacity - MAX_ARRAY_SIZE > 0) //新的容器长度大于 Integer.MAX_VALUE - 8 ?
            newCapacity = hugeCapacity(minCapacity); //大于则是Integer.MAX_VALUE
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity); //进行数组拷贝,yes yes yes 
    }

     private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

set()

    public E set(int index, E element) {
        rangeCheck(index); //判断是否越界

        E oldValue = elementData(index);  //保存旧值用于返回
        elementData[index] = element; //设置指定位置的指定值
        return oldValue; //返回旧值
    }

    private void rangeCheck(int index) {
        if (index >= size) // index >=size 就抛异常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

get()

    public E get(int index) {
        rangeCheck(index); //判断是否越界

        return elementData(index); //取出指定位置的值
    }

    private void rangeCheck(int index) {
        if (index >= size) // index >=size 就抛异常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

remove()

    public E remove(int index) {
        rangeCheck(index);  //判断index 是否越界

        modCount++; //修改次数 + 1 
        E oldValue = elementData(index);  //取出旧值,用于返回

        int numMoved = size - index - 1; 

        //这个看我下面的图
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);

        elementData[--size] = null; // clear to let GC do its work //用于gc回收

        return oldValue; //返回旧值
    }

    private void rangeCheck(int index) {
        if (index >= size) // index >=size 就抛异常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

image.png

trimToSize()

   public void trimToSize() {
        modCount++; //修改次数 + 1 
        if (size < elementData.length) { //元素个数是否小于于数组的容量
            elementData = (size == 0)  // 元素个数==0
              ? EMPTY_ELEMENTDATA //赋值空数组
              : Arrays.copyOf(elementData, size);//否则拷贝一个元素个数长度的数组
        }
    }

indexOf() 记得是用对象的equals来判断的

public int indexOf(Object o) {
        if (o == null) { //因为可以存null 所以需要判断是否是个null
            for (int i = 0; i < size; i++)
                if (elementData[i]==null) //是null 返回
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i])) //equals 
                    return i;
        }
        return -1;
    }

相关文章

网友评论

      本文标题:ArrayList 源码分析

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