一、层级关系
二、初始化方式
(1)List<String> list = new ArrayList<>();
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
第一个结论:ArrayList底层是数组
第二个结论:若用无参构造器的方式实例化ArrayList,只是声明了数组,还未分配空间
(2)List<String> list = new ArrayList<>(10);
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);
}
}
private static final Object[] EMPTY_ELEMENTDATA = {};
补充第二结论:若用有参构造器的方式实例化ArrayList且initialCapacity大于0,则既声明了数组,也分配了空间
三、基本方法的使用
add
- 流程图
- 源码解析
public boolean add(E e) {
//校验数组容量,若空间不够则扩容复制生成一个新的数组
ensureCapacityInternal(size + 1);
//赋值
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* 若数组是通过无参构造器的方式实例化的话,返回的minCapacity为10,最后会通过grow方法复制生成一个大小为10的数组
* 若数组是通过有参构造器的方式实例化的话,返回的minCapacity为当前要操作的数组下标,不建议声明小于10的数组空间,因为这样前几次add都要去扩容复制生成一个新的数组
*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//扩容大小:原数组大小 + 原数组大小/2
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时,不建议声明小于10的容量,因为这样前几次add都要去扩容复制生成一个新的数组
- Arrays.copyOf(T[] original, int newLength):该方法会创建一个新的数组
remove
- 流程图
- 源码解析
public E remove(int index) {
//检查index是否 >= size,若大于则报数组越界异常
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;
}
-
其它说明
- System.arraycopy - 浅复制
public static void arraycopy(
Object src, //源数组
int srcPos, //源数组要复制的起始位置
Object dest, //目标数组
int destPos, //目的数组放置的起始位置
int length //复制长度
)
四、补充
- ArrayList是线程不安全的,表现在多线程下add和remove可能会发生数组越界
- 不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。