ArrayList继承AbstractList并实现List, RandomAccess,Cloneable,java.io.Serializable接口
private static final int DEFAULT_CAPACITY = 10;
解析:默认容量
private static final Object[] EMPTY_ELEMENTDATA = {};
解析:空对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
解析:默认大小的空对象数组
transient Object[] elementData;
解析:数组缓存变量,ArrayList的容量是这个数组缓存变量的长度,关键字transient表示它的值不需要维持,不参与序列化
private int size;
**解析:**ArrayList大小
public ArrayList(int initialCapacity) {
// 如果初始化时ArrayList大小大于0
if (initialCapacity > 0) {
// new一个该大小的object数组赋给elementData
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 将空数组赋给elementData
this.elementData = EMPTY_ELEMENTDATA;
} else {
//抛出非法异常,比如说initialCapacity<0
throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
}
}
解析:构造方法 => 创建容量大小为initialCapacity的空的list
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
解析:构建方法=>创建一个默认长度(10)的空list
public ArrayList(Collection extends E> c) {
//将c容器转换为object类型的数组
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;
}
}
解析:带参数Collection构造方法,Collection有一下类型:
(注意:map也是经常用的集合类,但却没有实现Collection接口,map源码将在以后章节进行解析)
这里是将一个Collection实现类的对象转换为一个ArrayList,c容器装的内容必须为ArrayList装的内容的子类。很好奇什么情况下会出现elementData.getClass() != Object[].class,于是就查看了一下资料说java的一個bug 6260652,toArray() 有可能不會返回Object[]類型。Arrays.copyOf方法最终会调用System.arraycopy实现对数组的复制。
public void trimToSize() {
//modCount是从类 java.util.AbstractList 继承的字段,防止在多线程操作的情况下,List发生结构性的变化
modCount++;
if (size < elementData.length) {
// 重新将elementData设置大小为size
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
解析:
其中length > size,trimToSize方法就是剔除了为null的元素,将ArrayList的容量设置为当前size的大小,实现容量的压缩
//要分配的数组的最大大小
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//long int的最大值
public static final int MAX_VALUE = 0x7fffffff;
//得到最小扩容量
public void ensureCapacity(int minCapacity) {
//如果elementData为空,minExpand取0,否则去默认容量10
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
//扩容
ensureExplicitCapacity(minCapacity);
}
}
//得到最小扩容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//取最大值
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//扩容
ensureExplicitCapacity(minCapacity);
}
//判断是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果minCapacity大于elementData.length
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//动态扩容的核心方法
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
//新数组容量
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 判断新数组的容量够不够,
//够了就直接使用这个长度创建新数组,
//不够就将数组长度设置为需要的长度
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;
}
解析:最后grow()方法中
public int size() {return size;}
解析:返回ArrayList元素个数
public boolean isEmpty() {return size == 0;}
解析:判断ArrayList是否为空
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
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;
}
解析:对象o在ArrayList中的下标位置,如果存在返回位置i,不存在返回-1,如果o为空返回0
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
解析:返回容器内出现o的最后一个位置,从后向前遍历,得到第一个出现对象o的位置,不存在则返回-1
public Object clone() {
try {
// 调用父类Object类的clone方法得到一个ArrayList副本
ArrayList> v = (ArrayList>) super.clone();
//将原有对象的数据导入到新创建的对象中。
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0; //初始化modCount
//返回副本
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
**解析:**clone() 属于Object里面的方法,创建一个对象,然后将原有对象的数据导入到新创建的数据中。
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
解析:将list转化为一个数组,直接调用Arrays类的copyOf方法
public T[] toArray(T[] a) {
//如果a的长度小于ArrayList的长度,直接调用Arrays类的copyOf,返回一个比a数组长度要大的新数组,里面元素就是ArrayList里面的元素
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
//如果a的长度比ArrayList的长度大,那么就调用System.arraycopy,将ArrayList的elementData数组赋值到a数组,然后把a数组的size位置赋值为空。
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
解析:将ArrayList里面的元素赋值到一个数组中去
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
解析:检查是否越界,如果是抛出IndexOutOfBoundsException异常
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
解析: 先检查是否越界,然后返回ArrayList的elementData数组index位置的元素。
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
解析: 先检查是否越界,然后设置elementData数组index位置的元素为element。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
解析:扩容后将e赋值给elementData的size+1的位置
public void add(int index, E element) {
//判断是否越界
rangeCheckForAdd(index);
//扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
// 将elementData从index位置开始,复制到elementData的index+1开始的连续空间,size - index表示复制的元素的个数
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
解析:将特定元素element插入ArrayList的index位置
public E remove(int index) {
//查看是否越界
rangeCheck(index);
//对ArrayList进行删改时需要自增1
modCount++;
// 读取index位置的值
E oldValue = elementData(index);
// 获取index位置开始到最后一个位置的个数
int numMoved = size - index - 1;
if (numMoved > 0)
// 将elementData数组index+1位置开始拷贝到elementData从index开始的空间
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 使size-1 ,设置elementData的size位置为空,让GC来清理内存空间
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
解析:在ArrayList的移除index位置的元素。
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
}
public boolean remove(Object o) {
//判断o是否为空,如果为空
if (o == null) {
for (int index = 0; index < size; index++)
//将第一个出现为null的值移除掉
if (elementData[index] == null) {
fastRemove(index);
return true;
}
//如果不为空
} else {
for (int index = 0; index < size; index++)
//将第一个出现对象o的值移除掉
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
解析:在ArrayList的移除对象为O的元素。
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
//将elementData[i]置空,让GC来清理内存空间
elementData[i] = null;
//将size置0
size = 0;
}
解析:将list里面的所有元素移除,将会返回一个空的list。clear操作并不是从空间内删除,只是设置为null值,然后等待垃圾回收机制来回收,把size设置为0,以便我们不会浏览到null值的内存空间。
public boolean addAll(Collection extends E> c) {
//将c转换为数组
Object[] a = c.toArray();
//新增的长度
int numNew = a.length;
//扩容至size + numNew长度
ensureCapacityInternal(size + numNew); // Increments modCount
//将a的第0位开始拷贝至elementData的size位开始,拷贝长度为numNew
System.arraycopy(a, 0, elementData, size, numNew);
//size增加长度numNew
size += numNew;
//如果c为空,返回false,c不为空,返回true
return numNew != 0;
}
解析:将Collection c的全部元素添加到ArrayList中。
public boolean addAll(int index, Collection extends E> c) {
// 判断index大于size或者是小于0,如果是,则抛出IndexOutOfBoundsException异常
rangeCheckForAdd(index);
//将c转换为数组
Object[] a = c.toArray();
int numNew = a.length;
// 扩容至size + numNew
ensureCapacityInternal(size + numNew);
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
解析:从第index位开始,将c全部拷贝到ArrayList
private boolean batchRemove(Collection> c, boolean complement) {
final Object[] elementData = this.elementData;
// 定义两个变量w,r,同时右移
int r = 0, w = 0;
boolean modified = false;
try {
// r右移
for (; r < size; r++)
// 如果c中不包含elementData[r]这个元素
if (c.contains(elementData[r]) == complement)
// 则直接将r位置的元素赋值给w位置的元素,w自增
elementData[w++] = elementData[r];
} finally {
// 防止抛出异常导致上面r的右移过程没完成
if (r != size) {
// 将r未右移完成的位置的元素赋值给w右边位置的元素
System.arraycopy(elementData, r,
elementData, w,
size - r);
// 修改w值增加size-r
w += size - r;
}
if (w != size) {
// 如果有被覆盖掉的元素,则将w后面的元素都赋值为null
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
// 修改size为w
size = w;
modified = true;
}
}
return modified;
}
解析:根据complement值,将ArrayList中包含c中元素的元素删除或者保留。
public boolean removeAll(Collection> c) {
//如果c为null抛出NullPointerException异常
Objects.requireNonNull(c);
//调用batchRemove将list中存在于Collection c的元素移除
return batchRemove(c, false);
}
解析:将list中存在于Collection c的元素移除
public boolean retainAll(Collection> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
解析:将list中存在于Collection c的元素保留