//初始ArrayList容量
private static final int DEFAULT_CAPACITY = 10;
//empty_elemenData顾名思义,空数据常量用于初始化或者clean()方法
private static final Object[] EMPTY_ELEMENTDATA = {};
//反正就是一个空数组,经常赋值比较实用
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//这是组成ArrayList的基础,可以看到是一个Object类型的数组
transient Object[] elementData; // non-private to simplify nested class access
//记录ArrayList所装数据大小(其内部存储元素个数)
private int size;
//ArrayList最大大小为2^31-1-8。原因是在某些虚拟机中可能会存在一些头文字在数组中,所以我们为其保留空间放置内存溢出
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
3个构造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) { //initialCapacity大于0,则elemenetData = new Object[initialCapacity]初始化Object类型数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) { //initialCapacity等于0,换句话说初始化为空,那么elementData = {}。
this.elementData = EMPTY_ELEMENTDATA;
} else { //还一种情况就是initialCapacity小于0了,那么就throwException咯,数组初始化不可以为负数。
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//无参构造,初始化elementData = {};也为空
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//简单来说就是把一个集合转成ArrayList类型
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class) //elementData所指向的c.toArray()类型不是Object[]类型,则转换为Object[]类型
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
//调整大小
public void trimToSize() {
modCount++; //修改次数+1用于fast-fail,该属性继承与其父类AbstractList
if (size < elementData.length) { //当前数据大小小于ArrayList长度时,若存储数据为空(没存数据),则让elementData={},
elementData = (size == 0) //若size!=0 则让原Object[] elementData等于新的Object[]数据为原数据,elementData大小为
? EMPTY_ELEMENTDATA //原size
: Arrays.copyOf(elementData, size);
}
}
//确保ArrayList容量能包含指定最小容量minCapacity
//逻辑是这样的:如果elemenData为空那么我们把最小比较值minExpand赋值为10,若指定的最小容量minCapacity要比10大那么进行扩容准备操作 因为我们的elementData会默认为10的大小,如果elementData不为空那么直接进行扩容准备操作。
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) //当elementData不为空的时候minExpand为0,反之minExpand为10
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) { //如果指定的最小容量大于minExpand则进行孔若
ensureExplicitCapacity(minCapacity);
}
}
//确保ArrayList内部容量足够
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果当前ArrayList为初始化状态
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //若最低需求minCapacity大于初始化大小DEFAULT_CAPACITY则维持不动
} //若minCapacity低于DEFAULT_CAPACITY则最低需求变为ArrayList初始大小
ensureExplicitCapacity(minCapacity); //调用方法做出最后的确定以及修改
}
//最终确定清楚的ArrayList容量
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) //如果最低需求minCapacity都比当前ArrayList容量大,那么进行扩容操作
grow(minCapacity);
}
//扩容,扩容到elementData的容量能容下minCapacity指定的最小容量
private void grow(int minCapacity) {
int oldCapacity = elementData.length; //记录原Object[] elementData大小
int newCapacity = oldCapacity + (oldCapacity >> 1); //做扩容操作,newCapacity = oldCapacity + oldCapacity/2;
if (newCapacity - minCapacity < 0) //如果新容量newCapacity依旧小于指定的最小容量,那么让新容量变大为minCapacity所对应的值
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) //如果新容量大于ArrayList最大容量,则让新容量变为,
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //每次的扩容都是数组的数据复制,新的数组大小
}
//返回更大的Capacity
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) //如果入参不合格直接内存溢出异常
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? //如果minCapacity大于ArrayList的最大容量则返回Integer.MAX_VALUE反之则返回最大容量
Integer.MAX_VALUE : //MAX_ARRYA_SIZE
MAX_ARRAY_SIZE;
}
//返回size
public int size() {
return size;
}
//判断是否为空
public boolean isEmpty() {
return size == 0;
}
//判断是否包含一个元素
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
//从数组首位查找指定元素,如果查找的为null只返回ArrayList中Object[] elementData存储的第一个为null的元素下标,没有找到指定的元素则返回-1
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;
}
//从数组末位查找指定元素
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;
}
@return a clone of this <tt>ArrayList</tt> instance
//克隆一个ArrayList,返回一个ArrayList实例,因为返回类型是Object所以如果用ArrayList类型接的时候请强转一下。
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
//返回一个新的Object[]的数组,其实就是返回ArrayList中的elementData。但是他们的数据一样,引用不一样,也就是说你修改toArray所得的数组
//是不会影响原ArrayList的。
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
//同样的功能 ,把list的Object[] elementData复制以后放在T[] a中。
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size) //如果a的长度小于list的size
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass()); //就返回一个新的数组大小为list.size
System.arraycopy(elementData, 0, a, 0, size); //进行复制,从起始地elementData到目的地a,起点为0,长度为list.size
if (a.length > size)
a[size] = null;
return a;
}
//返回一个下标为index的元素
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
//返回一个下标为index的元素
public E get(int index) {
rangeCheck(index); //健壮性判断,入参index是否超出ArrayList.size 。是否超出ArrayList所含总元素数目
return elementData(index);
}
//在下标为index的地方放入一个元素(element),返回旧元素
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
//在ArrayList末尾元素后加上一个新的元素e(简单来说就是顺序添加)
public boolean add(E e) {
ensureCapacityInternal(size + 1); //确保ArrayList中的Object[] elementData一定有足够的容量,然后modCount(修改次数+1)
elementData[size++] = e; //在elementData[size]的位置上放上e元素,然后size++
return true;
}
//在指定的位置index上插入指定元素element
public void add(int index, E element) {
rangeCheckForAdd(index); //index>size||index<0 一种是index大于size的时候,一种是index入参不合理抛出异常
ensureCapacityInternal(size + 1); //确保ArrayList的容量足够,并且修改modCount属性值(用于fast-fail机制)
System.arraycopy(elementData, index, elementData, index + 1,
size - index); //这个操作很简单,简单来说就是把从index开始的元素往后挪一位(数组的插入操作而已)
elementData[index] = element; //挪完了之后就是把待插入的元素插入到index位置上
size++; //ArrayList中的元素总量size加一
}
//在指定位置index上删除一个元素,返回被删除元素
public E remove(int index) {
rangeCheck(index); //先对入参做出检查,若index>=size 抛异常,说明index指向了还未被赋值的数组位置
modCount++; //用于fast-fail机制
E oldValue = elementData(index); //在index位置找到对应元素,用于返回被删除元素
int numMoved = size - index - 1; //numMoved指的是需要移动多少个元素,因为你在数组中删除了一个元素之后该位置之后所有的元素都要往前移动一位
if (numMoved > 0) //有需要移动的元素
System.arraycopy(elementData, index+1, elementData, index,
numMoved); //从起始地elementData的起点index+1复制到目的地elementData的复制起始点index复制长度为numMoved
elementData[--size] = null; // clear to let GC do its work
//因为elementData[--size]这个位置是已经空了,但是它不会被GC回收,我们需要主动赋值null让GC进行回收
return oldValue;
}
//在ArrayList中删除第一个匹配指定的元素o,返回为true表示删除成功,返回false表示删除失败
//请注意!如果你要使用remove(Object o)方法的时候传入的参数一定跟储存在ArrayList中的元素的引用一样,不然删除不到你想要删除的元素。
public boolean remove(Object o) {
if (o == null) { //如果待删除元素为null则找到ArrayList中的第一个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;
}
//这个跟remove(int index)区别仅仅在于不对index进行判断且不返回被删除元素。。。emmmm
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
}
//把ArrayList的基层Object[] elementData数组全部赋值为null
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0; //我最后强调声明一次 size指的是ArrayList中被存储元素的个数,!不是!Obejct[] elementData数组的长度
}
//把一个集合的元素全部复制到ArrayList中,记住ArrayList的原数据不动!新增的数据在ArrayList原数组的末尾开始依次添加。返回true成功,false失败
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
//把一个集合的所有元素复制到从ArrayList的index位置开始。
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount //保证ArrayList的大小空间足够
//这是我们要把ArrayList原数组从index开始到size-1的位置上所有的元素个数(包括index),所以是size-1-index+1
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;
}
//范围删除,删除[fromIndex,toIndex)
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved); //删除等于,把删除终点之后的元素移动到删除起点
// clear to let GC do its work
int newSize = size - (toIndex-fromIndex); //新的ArrayList容量大小
for (int i = newSize; i < size; i++) {
elementData[i] = null; //然后再新终点之后的元素全为null
}
size = newSize;
}
//检查传入的index是否大于当前有效元素所在最大下标值。
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//检查index是否合格
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//拼接成了异常信息 Index:xxx, Size:xxx
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
Removes from this list all of its elements that are contained in the
* specified collection.
//从当前ArrayList中删除所有被c集合包含(在c中的)的元素。
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c); //这句就是简单的判断c集合是否为空
return batchRemove(c, false);
}
Retains only the elements in this list that are contained in the
* specified collection. In other words, removes from this list all
* of its elements that are not contained in the specified collection.
//简单的说就是,删除当前ArrayList中所有不被c集合包含(不在c中的)的元素
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
//顾名思义:批量删除 我们用removeAll方法做示例,我们默认complement为false
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0; //这里使用了双下标法,r用来遍历,w用来记录新生成的数组。
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement) //当前下标对应的元素不被c集合包含,你可以试想一下如果被包含(说明要被删除)
elementData[w++] = elementData[r]; //那么我们就不让elementData[w++] = elementData[r] 这样就等于更新数组了
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) { //为了防止异常的发生使元素丢失,说明r没有遍历完ArrayList就出现了Exception
System.arraycopy(elementData, r,
elementData, w,
size - r); //如果发生了异常,让后续r没有遍历完的元素直接移动到w下标的新位置
w += size - r; //简单来说就是删除到一半出问题了,接下来的不管是什么情况都把还没有检测的元素往前挪到新数组的末尾
}
if (w != size) { //说明删除了元素
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w; //被删除了几个元素 modCount就加几次
size = w;
modified = true; //标记,已修改
}
}
return modified;
}
//将ArrayList的实例状态保存到io流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
//从IO流中读出list来
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in capacity
s.readInt(); // ignored
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
//获得一个List的迭代器
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
//获得一个List的迭代器
public ListIterator<E> listIterator() {
return new ListItr(0);
}
//获得一个迭代器
public Iterator<E> iterator() {
return new Itr();
}