ArrayList源码阅读
属性字段
private static final long serialVersionUID = 8683452581122892189L;
//默认大小
private static final int DEFAULT_CAPACITY = 10;
//空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//从EMPTY_ELEMENTDATA独立出来,专门用于无参构造函数时的指向,起标识作用
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//默认数组
transient Object[] elementData; // non-private to simplify nested class access
private int size;
构造方法
1)无参构造函数
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
2) 参数为容器大小的构造函数
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);
}
}
3)参数为其他list的构造函数
public ArrayList(Collection extends E> c) {
//指向新数组
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray 可能返回的不是Object类型的数组所以加上下面的语句用于判断,
//这里用到了反射里面的getClass()方法
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
add添加
直接再末位添加元素
public boolean add(E e) {
//判断是否要扩容,并自增modCount
ensureCapacityInternal(size + 1); // Increments modCount!!
//添加元素
elementData[size++] = e;
return true;
}
指定位置添加元素
public void add(int index, E element) {
//验证下标是否在指定范围
rangeCheckForAdd(index);
//判断是否要扩容,并自增modCount
ensureCapacityInternal(size + 1); // Increments modCount!!
//复制数组,腾出空位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//添加元素
elementData[index] = element;
//大小加1
size++;
}
添加一个集合
public boolean addAll(Collection extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
//判断是否要扩容,并自增modCount
ensureCapacityInternal(size + numNew); // Increments modCount
//复制
System.arraycopy(a, 0, elementData, size, numNew);
//大小改变
size += numNew;
return numNew != 0;
}
扩容方法
ensureCapacityInternal()
实现对grow的封装
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
calculateCapacity()
第一次添加元素时,判断时扩容为默认大小,还是扩容为minCapacity.总感觉这是一个无用的方法
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
ensureExplicitCapacity()
改变modCount,并判断是否需要扩容,
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
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);
//在扩容为原来的1.5倍还不满足条件的时候
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 复制为一个新的数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//MAX_ARRAY_SIZE=8
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
remove删除
删除指定下标的元素
public E remove(int index) {
//判断范围
rangeCheck(index);
//自增modCount
modCount++;
//获得要删除的值
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
//把后面的值全部向前挪一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//最后以为置空,并减小数组大小size, 置空有利于GC回收
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
删除指定元素
public boolean remove(Object o) {
//如果要删除的元素是null,
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {//删除正常的值
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
//和删除指定下标元素的方法一样。
private void fastRemove(int index) {
modCount++;
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
}
get方法
很简单的逻辑
public E get(int index) {
//判断范围
rangeCheck(index);
//返回对应值
return elementData(index);
}
set方法
public E set(int index, E element) {
//判断范围
rangeCheck(index);
//获得旧元素
E oldValue = elementData(index);
//更新
elementData[index] = element;
//返回
return oldValue;
}