2-3 ArrayList注意事项
1.允许加入所有元素,包括null(并且可以添加多个null元素)
2.ArrayList是由数组实现数据存储的
3.ArrayList基本等于Vector,除了ArrayList是线程不安全(执行效率高)。在多线程情况下,不建议使用ArrayList。(没有syncrhonized关键字修饰)
2-4 ArrayList扩容机制
1.ArrayList中维护了一个Object类型的数组elementData
transient Object[] elementData; //transient表示瞬间,表示该属性不会被序列化
2.当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0。第一次添加,则扩容elementData为10.如果要再次扩容,则扩容elementData为1.5倍
3.如果使用的是指定大小的构造器,则初始elementData容量为指定大小。如果需要扩容,则直接扩容elementData为1.5倍
2-5 ArrayList 底层源码
ArrayList无参构造器
public static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList(){
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
ArrayList中add()源码
public boolean add(E e){
ensureCapacityInternal(size + 1);
elementData[size++] = e; //先把e赋值给elementData[size],之后size++
return true;
}
执行list.add():
(1)先确定是否要扩容
(2)然后再执行赋值
private static final int DEFAULT_CAPACITY = 10;
private void ensureCapacityInternal(int minCapacity) {
if(elementData == DEFAULTCAPACITY_EMPTY-ELEMENTDATA){
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
该方法确定minCapacity:
(1)第一次扩容为10
private void ensureExplicitCapacity(int minCapacity){
modmount++; //记录集合被修改的次数,防止多个线程同时修改。若多个线程同时修改,则会抛出异常
// minCapacity为集合所需最小容量 elementData.length为当前集合容量
//若minCapacity > elementData.length,说明所需容量比实际容量大,需要扩容
if(minCapcity - elementData.length > 0) {
grow(minCapacity);
}
}
(1)modCount++记录集合被修改的次数
(2)如果elementData的大小不够,就调用grow()去扩容
//真正的底层扩容算法
private void grow(int minCapacity){
int oldCapacity = lementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); //oldCapacity + oldCapacity/2 = 1.5
if(newCapacity - minCapacity < 0){ //如果newCapacity不能满足minCapacity需求
newCapacity = minCapacity; // 将minCapacity赋给newCapacity
}
if(newCapacity - MAX_ARRAY_Size > 0){
newCapacity = hugeCapacity(minCapacity);
}
// 数组复制,并扩大到newCapacity的长度,新增加的元素为null
elementData = Arrays.copyOf(elementData, newCapacity);
}
(1)真的扩容
(2)使用扩容机制确定要扩容到多大
(3)第一次newCapacity = 10
(4)第二次及以后,按照1.5倍扩容
(5)扩容使用的是Arrays.copyOf()