扩容机制主要由那么几个函数实现
private void ensureCapacityInternal(int minCapacity)
private void ensureExplicitCapacity(int minCapacity)
private void grow(int minCapacity)
依次讲一下
区别于ensureExplicitCapacity:
这个函数是口头上说,最少需要多少容量,但是还没去查它自己到底有多少。
相当这个函数相当于一个人评估自己最少需要多少钱能满足生活,但仅仅是评估而已,他自己还不知道自己家里有多少钱。
private void ensureCapacityInternal(int minCapacity) {
//判断一下当前的ArrayList是不是由无参构造函数构造的
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
※ 这个方法出现在 add() 和addAll()方法中,在 add()方法中调用 ensureCapacityInternal(size + 1), 因为add只是添加一个元素。
而在addAll()方法中则是 ensureCapacityInternal(size + numNew)。
※ 可以把这个方法看作是 “确保Arraylist的内部存储空间至少为 minCapacity”
※ 为什么要针对无参构造函数函数来做这样一个判断呢?因为无参构造函数的minCapacity比较特殊。通过其他构造函数生成的ArrayList,它们没有所谓的默认初始容量,所以要求的最小容量就是在add()或addAll()调用ensureCapacityInternal()方法时传入的minCapacity。
而无参构造函数不同,传入的minCapactiy可能会比DEFAULT_CAPACITY更小,那么此时就多给ArrayList分配点容量,所以 minCapacity = DEFAULT_CAPACITY ;而如果传入的minCapactiy比DEFAULT_CAPACITY更大,那么就和别的ArrayList一样了,分配minCapacity的容量就行了
这个函数就是在上一个函数评估的基础上,去查自己家里有多少钱,查出来如果家里的钱不够,那么就用 grow函数去增长,增长到 minCapacity
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
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)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
面试时记住这几个点就好:
① 增长为原来的1.5倍,如果增长后还是不够,那么就增长到minCapacity。那么这样的话,此时elementData数组是满的,没有剩余空间。
②如果数据太多,比MAX_ARRAY_SIZE还大了,就把空间容量扩大为Integer.MAX_VALUE
ArrayList有两个add()方法。
public boolean add(E e)
就是把元素插到尾部
public void add(int index, E element)
把元素插到指定的地方,原来的那个元素后退一格
关键是 System.arraycopy 来实现数组的移位操作,这个函数可以在做算法题的时候用,很方便。
public boolean addAll(Collection<? extends E> c)
public boolean addAll(int index, Collection<? extends E> c)
ArrayList有两个remove()方法。
public E remove(int index)
把指定下标的元素删除
public boolean remove(Object o)
从下标0开始循环,找到o后删掉。也就是说,只删除遇到的第一个
也是利用了System.arraycopy来对数组做整体移动。
之后再将最后一个元素作 elementData[size–] =null 的操作,让垃圾回收器去清理即可。
注意remove(Object o)中,对删除元素进行判断时,如果
o= =null ,则 利用 if(o==elementData[index]) 进行判断。
o!=null , 则利用 if(o.equals(elementData[index])进行判断。