底层实现:ArrayList的底层是一个数组,默认的数组长度为10
线程安全:ArrayList是线程不安全的
优点: ArrayList基于数组,所以擅长读取,在末尾add值也很快捷
缺点: 在指定下标add值的性能较差
ArrayList 默认值
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;
所有的数据都存储在elementData中
ArrayList的构造器
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
ArrayList有三个构造器:
(1)带有 initialCapacity 的构造器,如果我们可以确认生成的ArrayList的长度,建议创建ArrayList对象的时候带上初始化的容量值,避免内存空间的浪费
(2)无参的构造器,无参的构造器会使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA,使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA是为了在第一次加入值的时候计算应该扩充多大的ArrayList长度
(3)带有初始化Collection的构造器。会将size设置为Collection的长度,并使用Arrays.copyOf()方法将Collection的内容赋给elementData
添加一个元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
有两种添加元素的方式
(1): 直接添加到末尾
(2): 在指定下标处添加,需要先判断下标是否正确,同时需要将该下标之后的值都做相应的移位,会导致性能的降低
但无论何种方式,都需要先做ensureCapacityInternal() 判断,用于判断ArrayList对象的长度是否需要进行扩容
ensureCapacityInternal(size + 1)的过程
如果当前elementData的长度 已经无法满足 size+1的范围,则会进行扩容
扩容的大小为当前长度的1/2 + 1
如果这个长度仍无法满足size+1的要求,则ArrayList的长度会直接被设置为 size+1
代码如下:
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);
}
在扩容之后,如果ArrayList的长度大于Integer.MAX_VALUE - 8, 那么长度则直接设置为 Integer.MAX_VALUE
这意味着ArrayList的所能添加的值的最大个数为 Integer.MAX_VALUE.
获取一个元素
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
先需要判断下标是否正确,然后直接返回该下标对于的数组的值