从两个方面进行理解:
1.1、内部数组elementDate是咋样进行初始化的,初始化的长度是多少,这样才能知道什么时候容量不够用,要进行扩容了。
初始化数组是建立在两个构造方法上的:无参构造和有参构造。
1.1.1、无参构造方法:将当前的内部数组初始化为一个长度为0的空数组
让elementDate这个数组指向一个常量
这个常量定义为一个Object类型的空数组
1.1.2、有参构造方法:按照指定容量initialCapacity进行数组初始化
当传入一个指定的初始化容量200时
先进行判断,如果容量大于0,会按照初始化容量来创建elementData数组,如果容量等于0,就就让elementData数组初始化为一个空数组,如果容量小于0(负数),就会抛异常。
如果我们能预估当前我们要操作的数据的规模,那么就能一次性把数据添加到位,这样至少在添加前两百个元素时,内部数组是不会产生扩容。
因为空数组是不能存数据的,所以要进行扩容
1.2、扩容分两种情况:
1.2.1、当第一次添加元素时,数组扩容为10
用无参构造方法创建出一个空数组时,当我们向数组中添加第一个元素会调用add()方法,add()方法会将当前我们要添加的元素传进来。
而add()方法中会执行两个逻辑,一个是确保内部容量够用,二是将元素放进elementDate数组中。
但当前是一个空数组,所以我们进行扩容。
调用ensureCapacityInternal()方法,它的参数为size+1(size是当前数组的元素个数,+1是往数组中添加一个元素),用参数size+1来判断当前数组的容量。
这个方法中又调用calculateCapacity()方法,这个方法是用来计算容量和所需要的最小容量minCapacity。
在calculateCapacity()方法中,先判断elementDate数组是否为一个空数组,如果是一个空数组,就会返回DEFAULT_CAPACITY和minCapacity当中的最大值。
DEFAULT_CAPACITY:是一个常量,值为10。而minCapacit是传进来的参数,就是上面提到的size+1,值为1(数组为空,所以size为0,添加一个元素后,minCapacity就为1)
1<10,所以返回的minCapacity的值为10。
计算出来的minCapacity回传给ensureExplicitCapacity()方法,这个方法中如果minCapacity的值大于当前数组的长度,那就会以minCapacity的值10进行扩容。
1.2.2、当数组容量不足时,按照原来容量的1.5倍进行扩容增长
当我们向数组添加第十一个元素时,现有的size长度为10,所以传进去的参数为11,调用ensureCapacityInternal()方法。
因为现在不是一个空数组了,所以直接将参数11传给ensureExplicitCapacity()方法。
这个方法中会判断所需的最小容量减当前数组长度是否大于0,因为11-10>0,所以调用grow()方法。定义oldCapacity代表原来的容量,当知道原来的容量时,就可以在原来容量的基础上加上原来容量向右移一位(相当于除以2的一次方)。
int newCapacity = oldCapacity + (oldCapacity >> 1) 理解为:在原来容量的基础上再加上原来容量的一半,(就是原来容量的1.5倍)。
把 elementData数组中的元素复制到新的数组里,复制的个数是新容量的个数,所以新数组的长度就为15。既完成了数组的扩容,又把原来数组中的元素复制到新的数组中。
在扩容时,秉持的一个思想是:要尽量减少扩容的频率。