介绍
ArrayList是JAVA中一个非线程安全的集合类,里头采用数组进行存储,当容量不够时可以对数组进行扩容。
ArrayList的使用
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.get(1);//get(int index)
list.indexOf(1);//public int indexOf(Object o)
list.contains(1);//public boolean contains(Object o)
list.remove(2);//public E remove int index();
分析
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
如果没有传入参数,那么elementData就会先指向默认空数组。
开始学习一下ArrayList的add方法(cvte面试官竟然让我手写插入元素方法)
//add方法首先确保容量 size是数组中的元素容量,开始时0
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//如果elementData指向了默认空数组,那么minCapacity的大小是(size+1,10)最大的
//否则传入size+1大小
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
//modeCount++,这个是保证迭代过程安全的,当minCapacity大于原数组大小 扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//数组长度变为原数组长度的1.5倍
//如果1.5倍小于minCapacity则newCapacity赋值为minCapcatiy
//使用Arrays.copyOf(elementData,newCapacity)进行 数组动态扩容
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);
}
System.arrayCopy()
方法是一个native方法,用c/c++实现的。用于数组拷贝。
/*
src是要拷贝的数组,srcPos是数组起始位置,dest是目标数组,destPos是目标数组起始位置 length时拷贝多少个元素
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
System.arraycopy(elementData,0,a,0,size);
//删除源码
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; // clear to let GC do its work
return oldValue;
}
//add把元素添加到制定位置
//检查index是否越界,然后判断数组是否需要扩容,取出插入位置后面的元素,往后依次复制一格,放入元素
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
}