ArrayList的底层实现
1.底层实现为数组
默认无参构造方法是将初始化一个大小为16的数组,但在增删的时候会有个问题就是数组的扩容和缩小*(需要看源代码验证)
2.arraylist几种讲解
1)构造方法
public ArrayList() {
super();
this.elementData =EMPTY_ELEMENTDATA;
}
初始化一个大小为空的数组。
没有指定数组的容量大小的话就是一个空的数组。
让后往里add的时候会扩容,每次扩大1,再去比较,每次扩大1以后的大小比default_capacity小,如果是那么就将数组大小变为default_capacity(jdk1.7默认为10),扩容方法为ensureCapacity.那就从add方法开始看:
2)add方法
public booleanadd(E e) {
ensureCapacityInternal(size + 1);
// Increments modCount!!
elementData[size++] =e;
return true;
}
从源码中可以看出先判断数组大小是否满足要求。来看ensureCapacityInternal方法
private voidensureCapacityInternal(intminCapacity) {
if (elementData ==EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY,minCapacity);
//find the larger number between thenumber you put (or the //size+1)and the default capacity
}
ensureExplicitCapacity(minCapacity);
}
为了使得默认的数组大小要大于DEFAULT_CAPACITY,所以判断大小,用找出大的一个数之后,执行扩容动作,ensureExplicitCapacity方法。
private voidensureExplicitCapacity(intminCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity -elementData.length > 0)
grow(minCapacity);
}
扩容先记录操作次数,(protected transient int modCount = 0;)没操作一次就+1,grow方法是关键。
private voidgrow(intminCapacity) {
// 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);
}
将oldCapacity>>1再加上oldCapacity,这里是相当于1.5*oldCapacity-->newCapacity,判断newCapacity与最大可允许数组大小判断,再执行一个数组迁移的操作。
Arrays.copyof(elementData,newCapacity);
看源码:
public staticnativevoidarraycopy(Objects1, int Pos1,
Object s2, int Pos2,
intlength);
s1是目标对象,s2是数据来源对象,POS1是开始地方,length是复制的长度,pos2是数据输出的对象,
public ArrayList(intinitialCapacity){
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("IllegalCapacity: "+initialCapacity);
this.elementData =newObject[initialCapacity];
}
设置初始化ArrayList数组大小的构造方法。首先是super()执行父类的构造方法,Arraylist是继承了AbstractList<T>抽象类的,
3)get(int index)方法
知道了set方法之后,理解get方法简单很多。
public E get(intindex){
rangeCheck(index);
return elementData(index);
}
先判断index是否超出了最大值,超出抛出异常。
获得elementData[index],即table中这个位置的值。