ArrayList源码学习
- 本篇基于JDK1.8源码进行理解
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
RandomAccess 支持随机访问
Cloneable 支持对象拷贝 //实现clone方法
java.io.Serializable 支持序列化
private static final int DEFAULT_CAPACITY = 10;
调用无参构造器,数组默认为空(ArrayList == DEFAULTCAPACITY_EMPTY_ELEMENTDATA),当添加第一个元素的时候数组将被扩展到DEFAULT_CAPACITY大小
构造器
- 带一整型的构造器
public ArrayList(int initialCapacity) { //传入构造数组大小
if (initialCapacity > 0) { //如果大于0
this.elementData = new Object[initialCapacity];//创造对应大小的数组
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA; //空的数组 Object[] EMPTY_ELEMENTDATA = {};
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
- 无参构造器
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //参考下面add方法解释
}
- 带集合类的构造器
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
this.elementData = EMPTY_ELEMENTDATA;//集合类长度为0就直接替换为空数组
}
}
- add方法
// 计算数组大小能力
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//这里比较是否相等 就是直接内存地址
return Math.max(DEFAULT_CAPACITY, minCapacity);//这里分配数组大小 10 和 SIZE+1
}
return minCapacity;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // 列表修改次数 transient修饰
if (minCapacity - elementData.length > 0)// 如果要添加长度大于数组长度
grow(minCapacity); // 数组成长
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//最大长度
private void grow(int minCapacity) {
int oldCapacity = elementData.length; // 原先数组的长度
int newCapacity = oldCapacity + (oldCapacity >> 1);// 比如原先是10 那么新的长度为 10+10/2 = 15
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) // 直接异常
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?// 三元表达式
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 增加数组容量操作
elementData[size++] = e;// 将增加的对象添加到数组末尾
return true;
}
有以上代码可以看出
使用无参构造器的ArrayList当添加第一个元素时分配一个10长度的elementData
当添加第11个元素时elementData进行扩容 扩容到 int newCapacity = oldCapacity + (oldCapacity >> 1);
然后把元素添加到数组末尾elementData[size++]==e数组为0开头 size=10的位置即为第11个元素
- add 到指定位置
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
public void add(int index, E element) {
rangeCheckForAdd(index);//检查添加位置是否越界
ensureCapacityInternal(size + 1); // 此方法同上分析
System.arraycopy(elementData, index, elementData, index + 1,
size - index);// 本地方法进行数组copy空出index的位置
elementData[index] = element; // 设置对应index位置
size++;//长度加1
}
- get()方法 获取指定下标的元素
E elementData(int index) {
return (E) elementData[index];
}
public E get(int index) {
rangeCheck(index); //下标检查
return elementData(index);//数组下标获取元素
}
- clear()方法 清空ArrayList
public void clear() {
modCount++;//操作改变次数+1
// for循环置空 elementData.length不变 内容全部置空
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;//长度置为0
}
- remove 两种方法 指定位置 或者 指定对象
E elementData(int index) {
return (E) elementData[index];
}
public E remove(int index) {
rangeCheck(index); //检查越界
modCount++;//操作次数+1
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
//这里方便GC回收 同时发现remove元素后数组下标会进行移动
//切记不要在循环里删除元素从后面循环删除可以 但不建议 要移除元素建议使用迭代器
return oldValue;
}
//移除ArrayList某个元素 也可以发现这个方法只移除第一个发现的元素
public boolean remove(Object o) {
if (o == null) { //判断是否为空 因为为空无法使用equals方法
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++;// 结构改变次数+1
//下面这段和上面的移除一样
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
}
- set方法 set到指定位置 set方法并不会发生表结构改变
public E set(int index, E element) {
rangeCheck(index);//越界检查
E oldValue = elementData(index);// 获取老的值
elementData[index] = element;
return oldValue; //返回老的值
}
- isEmpty()方法
public boolean isEmpty() {
return size == 0;
}
- contains()方法
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
//遍历 和remove(Object o)一样道理 就是返回数组下标的值 都是从前开始返回第一个
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}