最近开始背面试八股文,本着死记硬背不如真正理解的想法。我会记录一下自己对一些题目的理解(前提是自己能理解得了)
开始正题首先是增方法均已add(E e)
先来看ArrayList的与增加有关的方法的源码
public boolean add(E e) {
//首先判断当前数组的大小是否能够达到size+1
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//判断数组大小的方法
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//计算当前数组的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果为数组为空,则返回指定大小与默认大小(默认为10)中大的那个
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//否则返回当前大小
return minCapacity;
}
//真正的判断&扩容数组的方法
private void ensureExplicitCapacity(int minCapacity) {
//将数组的修改次数+1 个人认为应该把这行放到grow()方法里
modCount++;
// overflow-conscious code
//如果需求大小(在非空数组的情况下为当前size+1)大于数组长度时进行扩容
if (minCapacity - elementData.length > 0)
//扩容方法
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
//存一下目前的长度
int oldCapacity = elementData.length;
//新的长度=目前的长度+位移一位的长度(0.5各oldCapcity)
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新的长度小于需求长度,则新的长度=需求长度
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新长度大于最大长度(Integer的MAX_VALUE-8),则将新长度设置为Inger的MAX_VALUE
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;
}
再来看vector的
// synchronized 修饰,线程安全
public synchronized void addElement(E obj) {
modCount++; //修改次数+1
//确保数组大小至少能够达到当前有效数量+1
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
//如果大于数组长度则扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//扩容机制与ArrayList大同小异
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//若指定了扩容大小,则扩容至当前大小+指定大小 负责扩容至当前大小的两倍
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
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;
}
addAll()与add(int index,E e)的逻辑也大同小异,这里不做过多说明。
结论:同:二者内部均为动态数组,且扩容逻辑大致相同。最终都是通过复制数组的形式来实现扩容
异:
每次扩容大小不同:
vector可以在构造函数中指定扩容大小,若不指定则每次扩容为原来的两倍。
arrayList无法指定扩容大小,每次扩容为原来的1.5倍
对线程安全的支持:
vetor的add方法有synchronized 关键字修饰,确保了线程安全
arrayList则没有,不保证线程安全



