ArrayList的几个成员变量
private static final int DEFAULT_CAPACITY = 10;//数组默认初始容量
/**
* 定义一个空的数组实例以供其他需要用到空数组的地方调用
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
定义一个空数组,跟前面的区别就是这个空数组是用来判断ArrayList第一添加数据的时候要扩容多少。
默认的构造器情况下返回这个空数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存数据的地方,它的容量就是这个数组的长度,同时只要是使用默认构造器(DEFAULTCAPACITY_EMPTY_ELEMENTDATA )第一次添加数据的时候容量扩容为DEFAULT_CAPACITY = 10
*/
transient Object[] elementData;
/**
数组的大小
*/
private int size;
扩容机制
从add方法说起
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
add方法中调用了ensureCapacityInternal()方法
ensureCapacityInternal 方法
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
//minCapacity是size+1
modCount++;
//判断是否需要修改数组大小
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
扩容的重点是grow()方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新的数组大小是按照原数组大小的1.5倍进行扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//当扩容量(newCapacity)大于ArrayList数组定义的最大值后会调用hugeCapacity
来进行判断,会抛出OutOfMemory 内存溢出异常
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);
}
Java容器的快速报错机制ConcurentModificationException
Java容器有一种保护机制,能够防止多个进程同时修改同一个容器的内容。如果你在迭代遍历某个容器的过程中,另一个进程介入其中,并且插入,删除或修改此容器的某个对象,就会立刻抛出ConcurrentModificationException。
前文提到的迭代遍历指的就是使用迭代器Iterator(ListIterator)或者forEach语法,实际上一个类要使用forEach就必须实现Iterable接口并且重写它的Iterator方法所以forEach本质上还是使用Iterator。