跟我一起来读java源码(一)

ArrayList

  • 构造函数
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;	
	private static final int DEFAULT_CAPACITY = 10; 
	private static final Object[] EMPTY_ELEMENTDATA = {};
	transient Object[] elementData;
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {        
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

我们先来看构造函数,ArrayList.java里面有几个变量,
final MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;设置最大数组大小,其中 Integer.MAX_VALUE为 java 中 int最大值 为的 2 的 31 次方 - 1 = 2147483648 - 1 = 2147483647,所以这里的值为 2147489647 - 8=214748363 9;

final DEFAULT_CAPACITY = 10默认大小为10

final Object[] EMPTY_ELEMENTDATA = {}设置一个空的object对象数组

transient Object[] elementData声明一个新的 Object 不被序列化的数组,这个数组是主要数组,所有的元素都将放在这个数组里面

当我们调用无参的构造函数时,初始化当前elementDataEMPTY_ELEMENTDATA,即为空。

当我们调用有初始化大小的构造函数时,判断initialCapacity是否大于零,大于则初始化一个大小为
initialCapacity的Object对象数组。等于零则初始化当前elementDataEMPTY_ELEMENTDATA,即为空
当小于零,抛出错误

当我们调用参数为集合的构造函数时,此构造函数的意思是将集合转为ArrayList,
先将 参数转为数组并赋给elementData,判断当elementData长度不为零时,判断是否成功将参数集合转化为Object类型的数组,如果转化成Object类型的数组成功,则将数组进行复制,转化为Object类型的数组。
elementData长度为零时,则初始化当前elementDataEMPTY_ELEMENTDATA,即为空。

  • 扩容
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  //扩容
       ...
  
    }

	private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
	private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//判断是否为空,为空则返回初始值和设置值中最大的部分
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;//否则返回设置值
    }
	private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//记录修改次数

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)//判断大小是否大于当前list对象的长度
            grow(minCapacity);//长度增加
    }
	 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//未增加前长度
        int newCapacity = oldCapacity + (oldCapacity >> 1);//位运算,让长度增加原来的1.5倍
        if (newCapacity - minCapacity < 0)//当扩容后的长度小于增加后的长度,
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)//当扩容后的长度大于最大大小时
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);//复制扩容并令当前对象等于它
    }
	private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow溢出
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
        //当长度大于最大长度,则返回int类最大值,否则返回最大长度
        //源码上有写最大长度=int类最大值-8
    }

扩容函数为add()函数调用,函数主体是ensureCapacityInternal,参数为未扩容前大小+1,
调用 ensureCapacityInternal(int minCapacity)函数后,
再调用 calculateCapacity(Object[] elementData, int minCapacity),这个函数有两个参数,一个是当前elementData,一个是扩容后的大小 ,这个函数的作用是,判断elementData是否为空,如果是,则返回默认大小和扩容后大小的最大值,如果不为空,则直接返回扩容后的大小
然后调用ensureExplicitCapacity()这个函数的参数是 校验后的 minCapacity,这个函数的作用是,开始先将修改步骤++,即 modCount++ ,然后执行grow() 进行扩容,
minCapacity表示集合为了确保添加元素成功的最小容量。在扩容的时候,首先将原元素数组的长度增大1.5倍(oldCapacity + (oldCapacity >> 1)),然后对扩容后的容量与minCapacity进行比较:① 新容量小于minCapacity,则将新容量设为minCapacity;②新容量大于minCapacity,则指定新容量。最后将旧数组拷贝到扩容后的新数组中。
在这里插入图片描述在这里插入图片描述
资料:
copyOf详解
modCount
transient

发布了29 篇原创文章 · 获赞 33 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42568510/article/details/101373602
今日推荐