ArrayList的注意事项
1)permits all elements,including null,ArrayList可以加入null值,并且可以加入多个
2)ArrayList是由数组来实现数据存储的
3)ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码,
在多线程情况下,不建议使用ArrayList
ArrayList底层结构和源码分析
ArrayList的底层操作机制源码分析(重点、难点)
1)ArrayList中维护了一个Object类型的数组elementData.[debug看源码]
transient Object[] elementData; // 表示瞬间的,短暂的,表示该属性不会被序列化
2)当创建ArrayList对象时,如果使用的是无参构造,则初始elementData容量为0,
第一次添加,则扩容elementData为10,如果需要再次扩容,则扩容elementData为1.5倍。
3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,
则直接扩容elementData为1.5倍。
ArrayList源码分析
// 1.创建一个空的elementData数组{}
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}
// 2.执行list.add
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 先确定是否要扩容,然后再执行赋值
// 3.该方法,确定minCapacity,第一次扩容为10
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
// 4.modCount++记录几何被修改的次数
// 如果elementData的大小不够,就调用grow()扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/*
5.1 真的扩容
5.2 使用扩容机制来确定要扩容到多大
5.3 第一次newCapacity = 10
5.4 第二次及以后按照1.5倍扩容
5.5 扩容使用的是Arrays.copyOf()
*/
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);
}