ArrayList作为一个新手最常用的集合,一直都没有研究他内部的实现,既然下定决心要写博客,就不管什么大小事都记录一下吧,或许真的有用呢?
首先ArrayList有三个构造函数(jdk8)
1. new ArrayList();
2. new ArrayList(int initialCapacity);
3. new ArrayList(Collection<? extends E> c);
由于ArrayList的内部就是一个数组,所以它的构造函数都是对Object [] elementData进行初始化
下面看看ArrayList是如何实现增删的
public boolean add(E e) {
ensureCapacityInternal(size + 1 );
elementData[size++] = e;
return true ;
}
public void add(int index , E element) {
rangeCheckForAdd(index );
ensureCapacityInternal(size + 1 );
System.arraycopy(elementData, index , elementData, index + 1 ,
size - index );
elementData[index ] = element;
size++;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0 )
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1 );
if (newCapacity - minCapacity < 0 )
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0 )
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
public E remove(int index ) {
rangeCheck(index );
modCount++;
E oldValue = elementData(index );
int numMoved = size - index - 1 ;
if (numMoved > 0 )
System.arraycopy(elementData, index +1 , elementData, index ,
numMoved);
elementData[--size] = null ;
return oldValue;
}
public boolean remove(Object o) {
if (o == null ) {
for (int index = 0 ; index < size; index ++)
if (elementData[index ] == null ) {
fastRemove(index );
return true ;
}
} else {
for (int index = 0 ; index < size; index ++)
if (o.equals(elementData[index ])) {
fastRemove(index );
return true ;
}
}
return false ;
}
private void fastRemove(int index ) {
modCount++;
int numMoved = size - index - 1 ;
if (numMoved > 0 )
System.arraycopy(elementData, index +1 , elementData, index ,
numMoved);
elementData[--size] = null ;
}
1. 总体来说add方法都是先检查数组大小是否需要扩容,再赋值。由于ArrayList是非线程安全,在多线线程的情况下,请勿使用,例如2 个线程同时对一个数组插入数据,当size==9 时,2 个线程同时通过了ensureCapacityInternal检查的情况下,就会出现java.lang.ArrayIndexOutOfBoundsException
2. 每次删除都需要用System.arraycopy对数组进行复制,例如arr[1 ,2 ,3 ,4 ],若把arr[1 ]删除,就要把arr[2 ]后面的内容,复制到原来的位置上,由于不是java的方法不能进入内部查看。
3. 这样就清楚ArrayList增删没有LinkedList快的原因了。