解释ArrayList的源码
package java.util;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import sun.misc.SharedSecrets;
实现RandomAccess这个接口的 List 集合是支持快速随机访问,for循环比迭代器快
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
//默认初始容量为10个,也就是如果初始化数组的时候不指定ArrayList大小,
默认为10个。
ArrayList<String> strs = new ArrayList<String>();使用无参构造方法时并
没有初始化数组大小,会默认大小为10,但是在初始化的时候不会设置为10个,
会在第一次执行add操作的时候扩容为10个
private static final int DEFAULT_CAPACITY = 10;
//如果初始化size设置为0的话,会使用这一个数组
private static final Object[] EMPTY_ELEMENTDATA = {};
如果使用无参构造方法创建的ArrayList实例,会使用这一个数组。使用这个也是
区分其他的创建实例的方式,来判断初始化数组的大小。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//真正存储ArrayList数据的数组,不用private修饰是为了让内部类访问简单一些
transient Object[] elementData;
//数组的大小,并不是elementData的大小,是实际存放元素的个数。
private int size;
//构造一个具有指定初始容量的空列表。 如果初始化容量>0,new一个初始化容量
//的数组,赋值给elementData ,如果=0,使用共用变量,否则<0,抛出异常
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);
}
}
//使用无参构造方法时,直接使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//通过一个集合创建ArrayList,将传入集合中的元素一个个地放进数组中。
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();//该方法不传参数只能返回Object类
if ((size = a.length) != 0) {
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
//modCount:在父类中AbstractList中定义的,初始为0,判断这个ArrayList
//结构上被修改的次数,一般用于fast-fail模式,当这个ArrayList的迭代器
//调用next、remove、previous、set、add方法的时候,会通过ArrayList的
//这个字段判断数组是否发生变化,如果发生了变化,将报出异常。
//这个方法的作用是将ArrayList中存放元素的Array的大小调整为实际元素
//的个数。减少ArrayList实例的存储空间,如果大小为0的话,赋值为
//EMPTY_ELEMENTDATA
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
//array的最大能扩容到的长度
//有些VM在array中需要一个头部的数据,所以要-8
//如果大小超过这个大小,可能出现内存溢出的异常
//如果你的数组大小不能设置成这么大,可能是VM配置或硬件问题(这个没有研究过)
//https://blog.csdn.net/weixin_30810583/article/details/96248144(看看这个)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//大容量扩容,这个函数只能是尽量给你扩容,但是能不能扩还要看VM支持不支持,
//详见上面的MAX_ARRAY_SIZE解释
private static int hugeCapacity(int minCapacity) {
//如果数值太大导致内存溢出,出现负数的情况,直接抛出异常
if (minCapacity < 0)
throw new OutOfMemoryError();
//如果数值大于MAX_ARRAY_SIZE,只能赌一下你的VM不会在array中添加一个头部的数据
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
//扩容以确保它至少可以容纳参数指定的元素数。
//这块代码可能出现溢出的情况
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
//java策略产生的扩容数量,即1.5*原来的的容量,右移为*0.5
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果java默认策略的扩容数量无法达到参数指定的最小容量,那么放弃默认策略,
//按照参数指定的容量进行扩容,如果默认策略大,就按照策略的。
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//判断扩容后的容量是否>数组的最大容量,可能出现风险,要用参数的试一下,因为
//对于本次扩容扩容来说,参数值肯定是最小的,试试这个最小值(newCapacity可能
//因为比参数大,导致用的是策略的值)。
if (newCapacity - MAX_ARRAY_SIZE > 0)
//执行大容量扩容的函数,这个函数可能会出现异常
newCapacity = hugeCapacity(minCapacity);
//将原来的数组复制到一个新的数组中(新数组的长度是扩容后的长度)
elementData = Arrays.copyOf(elementData, newCapacity);
}
//作用就是根据传过来的容量,判断是不是需要扩容,只有需要的容量大于当前容量,才要扩容
private void ensureExplicitCapacity(int minCapacity) {
//这个modCount++执行了,但是如果需要的容量<=当前容量的时候,ArrayList的结构是
//不会发生变化的,也就是说modCount变化并不代表真的变了。Iterator抛出异常并不代表
//ArrayList变了
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//根据参数去扩大ArrayList的容量
public void ensureCapacity(int minCapacity) {
//判断是不是通过无参构造方法创建的ArrayList实例(只有用无参构造方法才会是这个)
//如果是的话,他的默认大小已经是10了,所以不能比他小
///如果不是,可以是任意数,因为如果是其他的方法创建的实例,大小可能是>0的任意数
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
? 0
: DEFAULT_CAPACITY;
//只有符合最小值才能去扩展
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
//这个方法和上面的方法的区别是:
//ensureCapacity:如果传入的minCapacity不符合最小的值,就不会进一步给你扩容了,可能是你
//数字输入错误,但是方法方法不知不觉的不给你执行下面的扩容
//ensureCapacityInternal:如果传入的minCapacity不符合扩容最小值,会计算出一个合适的值去
执行下面的扩容过程
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//通过传入的最小参数,给出一个适合的扩展值。和ensureCapacityInternal配合使用
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//返回ArrayList的元素数量(不是总容量)
public int size() {
return size;
}
//判断ArrayList中是否有元素
public boolean isEmpty() {
return size == 0;
}
//如果参数在ArrayList中存在(equals(包括null)),则返回true,否则,返回false,详见indexOf函数
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
//查询出该元素在ArrayList中第一次出现的位置,如果不存在则返回-1,通过equals进行判断
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;
}
//查询出该元素在ArrayList中最后一次出现的位置,如果不存在则返回-1,通过equals进行判断
//这个可以记一下,第一次出现的位置从第一个开始遍历,最后一次出现的位置从最后一个开始遍历
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;
}
//ArrayList的一个浅克隆
//深克隆(虽然说v.elementData对象变化了,但是这个elementData数组中的引用却由于copyOf是
一个浅拷贝,elementData中元素的对象引用没有发生变化,当这个elementData中的元素发生变化
时,被克隆和克隆的对象都会变化。所以这个是一个浅拷贝被克隆的对象和克隆的对象内部出现一个
相同的引用,都不叫深克隆)
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
//把里面的元素拷贝一份
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
//ArrayList转化成Array
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
//将ArrayList中的内容放到传进来的数组中
//如果传进来的数组小于ArrayList的大小,直接重新建一个数组传出去
//否则将ArrayList中的元素拷贝进传进来的数组中
//如果传进来的数组大于ArrayList的大小,在index=size的位置置为null,
//用来判断结尾。在程序中设置为null是为了放置传进来的数组里面有内容。
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
//访问ArrayList中固定位置的元素
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
//检测传进来的下标是否合理(0~size),很多方法用到,所以单独出来的方法,不去判断<0
//让数组自己报错。
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//访问ArrayList中固定位置的元素,多了一个rangeCheck,外面直接调用这个就行
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
//使用一个元素替代指定位置原来的元素
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
//在ArrayList中的array最后添加元素
public boolean add(E e) {
//调用这个方法会使modCount+1
ensureCapacityInternal(size + 1);
//size+1并设值,这个写法很不错
//element[size] = e ;size ++ => elementData[size++] = e;
elementData[size++] = e;
return true;
}
//在指定位置添加元素,并将该位置和该位置后面的元素后移
public void add(int index, E element) {
rangeCheckForAdd(index);
//每次添加元素前都要看看是不是要扩容
ensureCapacityInternal(size + 1);
//arraycopy不仅仅用于两个数组,可以一个数组之间复制
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//删除指定位置的元素,并且将该元素后面的往前移动,返回删除的元素
public E remove(int index) {
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 ; size--
elementData[--size] = null;
return oldValue;
}
//删除ArrayList中的指定元素(第一个出现的),并返回删除结果
public boolean remove(Object o) {
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
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null;
}
//将ArrayList中的元素置为null,并且将size变成0
public void clear() {
modCount++;
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
//将一个集合中的元素加入到ArrayList的array中
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
//将集合中的元素插入到ArrayList中,插入位置和插入位置后的元素移动集合的长度个单位,返回
添加的结果
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
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;
}
//将ArrayList下标范围内的元素删除
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);
for (int i = newSize; i < size; i++) {
elementData[i] = null;
}
size = newSize;
}
//添加元素时做的范围检查,这个必须要判断是否小于0,因为添加的时候会有下面的操作
//扩容或者调整元素,如果在调整过程中发现越界,前面的操作无法撤回。Index为什么要
//小于等于size:System.arraycopy(elementData, index, elementData, index + 1,
//size - index);如果index>size,最后一个参数<0,这个函数会报错,但是=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;
}
//将ArrayList中包含的c集合的元素删除掉,需要判断c不为null.
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
//和removeAll相反,这个方法留下的是和c集合的元素相同的元素.
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
//批量删除ArrayList中的元素,通过complement来判断是否保留/删除c的元素。
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
//设置更改状态为false
boolean modified = false;
try {
for (; r < size; r++)
//遍历整个array,将需要保留的数据放在前面
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
//这个注释也不知道是什么意思
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
//如果发生异常导致未遍历完成,那么将未遍历的元素放在后面,当成是需要保留的数据
if (r != size) {
System.arraycopy(elementData, r,elementData, w,size - r);
//保留的数据个数需要添加上后面没有遍历的数据个数
w += size - r;
}
//将保留的数据后面的位置置为空,并且更改size为保留的数据的个数
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
//将ArrayList序列化到文件中。用ObjectOutputStream的writeObject方法时会调用这
个方法去写入磁盘
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();
}
}
//通过文件流反序列化成ArrayList对象
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
s.defaultReadObject();
s.readInt(); // ignored
if (size > 0) {
int capacity = calculateCapacity(elementData, size);
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, 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();
}
}
}
//ArrayList内部自己定义的Iterator
private class Itr implements Iterator<E> {
int cursor; //下一个返回元素的索引
int lastRet = -1; //当前遍历到的位置的索引
int expectedModCount = modCount;记录创建迭代器的modCount
Itr() {} //无参构造方法
//判断是否遍历完成,后面是否有元素
public boolean hasNext() {
return cursor != size;
}
//判断在迭代器(Itr)创建之后ArrayList是否发生变化,如果发生变化,直接抛出异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
//获取cursor处的元素(即下一个元素,因为cursor指的是当前遍历的下一个位置)
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
//共享的变量都不可靠
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
//游标往后移动一位,下一个位置
cursor = i + 1;
//返回当前遍历到的元素,并且修改当前位置LastRet,因为下一个已经取出来了,所以当前
//位置应该修改
return (E) elementData[lastRet = i];
}
删除当前遍历到的元素(只能删除最后一次遍历到的元素,如果这个元素被删除,lastRet需
要变成-1,如果不变的话,下一次调用删除这时候删除的就不是最后一次遍历到的元素了,删
除不能乱删除,如果说lastRet不变的话,这个删除函数就没有道理了,我函数没有指定哪个下
标的元素,就给我删除了,这不是乱删除吗,如果我置成-1,这个函数的原理就是删除最后一次
遍历到的元素,在删除一次后下一次就不能删除了。因为当前遍历到的元素已经没了。所以置成
-1)
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
//调用ArrayList自己的方法去删除ArrayList的元素
ArrayList.this.remove(lastRet);
//cursor移动到当前位置,因为是删除了一个,所以下一次遍历应该是当前位置
cursor = lastRet;
//lastRet修改为-1
lastRet = -1;
//同步modCount的值
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
//对剩余的元素进行操作(从cursor开始到最后),consumer.accept是对剩余元素的操作)
//Consumer是函数式接口.
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
//当没有遍历到最后一个元素且ArrayList没有被其他程序修改的时候。
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
//重新修改cursor的值,如果这样的话,其实这个函数针对的是最后面的几个操作相同,前面的操作不同的情况,最后这几个直接一次遍历完
cursor = i;
//修改lastRet
lastRet = i - 1;
checkForComodification();
}
//ArrayList自己定义的一个ListIterator
private class ListItr extends Itr implements ListIterator<E> {
//传入起始位置,从该位置开始遍历
ListItr(int index) {
super();
cursor = index;
}
//判断当前位置前面是否有元素
public boolean hasPrevious() {
return cursor != 0;
}
//返回接下来要遍历元素的下标
public int nextIndex() {
return cursor;
}
//返回前一个元素的坐标(针对接下来要遍历的元素下标来说)
public int previousIndex() {
return cursor - 1;
}
//返回前一个元素(针对接下来要遍历的元素下标来说)
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
//修改当前遍历到的位置的元素
public void set(E e) {
//lastRet<0说明当前元素已经删除或者迭代器还没有遍历,所以说没有当前遍历到的元素
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
//调用ArrayList自己的方法去修改ArrayList的元素
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
//在当前遍历到的位置添加一个元素
public void add(E e) {
checkForComodification();
try {
int i = cursor;
//调用ArrayList自己的方法在当前位置去添加元素
ArrayList.this.add(i, e);
cursor = i + 1;
//因为当前位置已经不是遍历到的元素了,所以置为-1
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
//创建一个ListItr,从ArrayList的指定位置开始
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
//创建一个ListItr,从ArrayList的第一个位置开始
public ListIterator<E> listIterator() {
return new ListItr(0);
}
//创建一个Itr,从ArrayList的第一个位置开始
public Iterator<E> iterator() {
return new Itr();
}
//使用自己的内部类截取ArrayList本身的一部分
public List<E> subList(int fromIndex, int toIndex) {
//截取之前对截取的位置做一下判断
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
//对截取的位置进行判断
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
//截取ArrayList中的一部分。需要注意的是,这个内部类只能被外部类调用
//因为这个内部类由private修饰,无法使用Out.In in = new Out().new In()
//这种方式被其他的类访问,而外部类中调用内部类的方法为subList方法,它
//调用这个类的构造方法时,传进来的参数是ArrayList本身。所以这个内部类
//主要的作用就是截取外部类实例的一部分,并不能截取其他的对象。然后其实
//这个类的操作是和ArrayList相似的,且大多调用的是ArrayList本身的方法,
//唯一不一样的是起始位置不同,所以subList中的方法和ArrayList本身的操作
//就是多了一个偏移量。这部分将粗略说明,如果不懂,可以看ArrayList的同名
//方法。还有就是subList中的所有操作都是针对外部类对象ArrayList中的内容
//进行修改的
private class SubList extends AbstractList<E> implements RandomAccess {
//原来的集合,其实就是外部类的实例
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
SubList(AbstractList<E> parent,int , int fromIndex, int toIndex) {
this.parent = parent; //外部类实例本身
this.parentOffset = fromIndex; //截取开始位置
this.offset = offset + fromIndex; //offset是0,所以offset = parentOffset
this.size = toIndex - fromIndex; //截取的长度
this.modCount = ArrayList.this.modCount;//因为截取的是外部类实例本身,所以用外部
类的modCount
}
//判断该位置是否超出了subList的边界
private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//判断外部的modCount是否发生变化,也就是他的结构是否发生变化
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
//修改index处的值,注意一点:这个subList的策略是:当执行set、get操作时
//考虑了偏移量(offset),其他的情况并没有计算偏移量。也就是说外面
//传递进来的offset是用于获取某个index处的值或者设置某一个index处的值时用的。
//,如果是截取的subList的外部类对象,其实是没有问题的,因为外部类调用时offset
//设置的是0,对于结果上来说没有影响。但是我不是很清楚这样设计的用意,就不解释了。
//如果某一天其他的对象调用到了这个私有内部类(应该不太可能),就需要注意了,设置
//获取的时候使用了偏移量,其他情况没有使用偏移量。看看subList的方法是否会对结果
//有影响。
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
//使用ArrayList.set相同的做法,不同的是index是加了offset
//下面很多都是这样的
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
//获取index处的值
public E get(int index) {
rangeCheck(index);
checkForComodification();
//这里也是计算了偏移量
return ArrayList.this.elementData(offset + index);
}
//返回subList的长度,也就是截取的长度
public int size() {
checkForComodification();
return this.size;
}
//在index处添加一个元素,添加元素时没有考虑offset偏移量的问题
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
//调用父类的add方法,是从截取的初始位置开始计算的。
//很正常的操作
parent.add(parentOffset + index, e);
//外部类对象结构变化了,需要重新获取modCount
this.modCount = parent.modCount;
//虽然针对外部类进行操作,且fromIndex和toIndex没有变化,但是size还是要++,
//刚开始的fromIndex和toIndex是为了第一次初始化的,以后就没什么用了,因为
//对subList执行了add操作,所以从逻辑上讲subList的长度是要+1的
this.size++;
}
//删除某一个位置的数据
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = parent.remove(parentOffset + index);
this.modCount = parent.modCount;
this.size--;
return result;
}
//删除一个范围内的数据
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
parent.removeRange(parentOffset + fromIndex,
parentOffset + toIndex);
this.modCount = parent.modCount;
this.size -= toIndex - fromIndex;
}
//将c中的元素全部添加到subList的末尾
public boolean addAll(Collection<? exends E> c) {
return addAll(this.size, c);
}
//在index位置把c中的元素全部添加
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false;
checkForComodification();
parent.addAll(parentOffset + index, c);
this.modCount = parent.modCount;
this.size += cSize;
return true;
}
//将subList生成一个迭代器,调用的是父类AbstractList中的方法,从subList的第
//0位开始遍历
public Iterator<E> iterator() {
return listIterator();
}
//将subList生成一个迭代器,调用的是父类AbstractList中的方法,从subList的第
//index位开始遍历
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
final int offset = this.offset;
//一个匿名内部类,实现了ListIterator接口,操作和ArrayList的迭代器操作差不多
return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = ArrayList.this.modCount;
public boolean hasNext() {
return cursor != SubList.this.size;
}
//subList的迭代器的原则和sublist的原则一样,设置、获取元素时,考虑偏移
//添加删除不考虑偏移
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
}
public boolean hasPrevious() {
return cursor != 0;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[offset + (lastRet = i)];
}
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = SubList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[offset + (i++)]);
}
// update once at end of iteration to reduce heap write traffic
lastRet = cursor = i;
checkForComodification();
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(offset + lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (expectedModCount != ArrayList.this.modCount)
throw new ConcurrentModificationException();
}
};
}
//subList还可以再次截取,变成另外一个subList,但是操作的还是外部类对象
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, offset, fromIndex, toIndex);
}
//判断index是否超出sublist的范围
private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+this.size;
}
//将subList转换成ArrayListSpliterator,其中开始位置设置为offset,结束位置为offset
+subList的大小
public Spliterator<E> spliterator() {
checkForComodification();
return new ArrayListSpliterator<E>(ArrayList.this, offset,
offset + this.size, this.modCount);
}
}
//将ArrayListlist中的元素做同一个操作,就是相当于for循环,传递的Consumer函数接口就是对
//ArrayList中所有元素的操作
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
//将ArrayList生成一个spliterator
@Override
public Spliterator<E> spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, 0);
}
//实现util包中的Spliterator接口(可以被切割的迭代器)
static final class ArrayListSpliterator<E> implements Spliterator<E> {
private final ArrayList<E> list;
private int index;
private int fence;
private int expectedModCount;
ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list; //被迭代的ArrayList本身
this.index = origin; //起始位置orgin翻译过来也是有原点起源的意思
this.fence = fence; //最终位置
this.expectedModCount = expectedModCount;
}
private int getFence() {
int hi; // (a specialized variant appears in method forEach)
ArrayList<E> lst;
//第一次调用getFence()的时候,因为ArrayList传进来为-1,相当于初始化fence
if ((hi = fence) < 0) {
//如果传进来的list是null,设置fence设置为0
if ((lst = list) == null)
hi = fence = 0;
//否则设置ArrayList的size,所以fence记录的是ArrayList的大小,并且初始化
//expectedModCount为list的modcount,方便查看ArrayList是否发生结构性变化
else {
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
//返回ArrayList的大小
return hi;
}
//将这个ArrayListSpliterator拆分为两个ArrayListSpliterator
public ArrayListSpliterator<E> trySplit() {
//得到中间的位置右移一位相当于是/2
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
//如果初始位置>=最后的位置,说明已经不能再去分割了
return (lo >= mid) ? null : // divide range in half unless too small
//如果能够分割,将右边的一半赋值给新的ArrayListSpliterator,并未进行真正的
//只是将两个ArrayListSpliterator的可操作性区域进行了设定
new ArrayListSpliterator<E>(list, lo, index = mid,
expectedModCount);
}
//获取遍历到的元素,并按照传进来的实现的接口的方法进行操作
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
int hi = getFence(), i = index;
//判断index是否超过ArrayListSpliterator的最大范围
if (i < hi) {
//将index移动到下一个
index = i + 1;
//得到当前位置的元素
@SuppressWarnings("unchecked") E e = (E)list.elementData[i];
//操作当前元素
action.accept(e);
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
//操作剩余的元素,即index到fence处的元素
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst; Object[] a;
if (action == null)
throw new NullPointerException();
if ((lst = list) != null && (a = lst.elementData) != null) {
if ((hi = fence) < 0) {
mc = lst.modCount;
hi = lst.size;
}
else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
//返回剩余元素个数
public long estimateSize() {
return (long) (getFence() - index);
}
//返回该Spliterator的特性
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
//根据传进来的Predicate函数式接口,来判断元素是否要被删除,根据他来删除元素
@Override
public boolean removeIf(Predicate<? super E> filter) {
//每次都是先判断传递进来的是不是非空
Objects.requireNonNull(filter);
//初始化要删除的元素个数为0
int removeCount = 0;
//创建一个bitSet来记录要删除的元素的下标
final BitSet removeSet = new BitSet(size);
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
@SuppressWarnings("unchecked")
final E element = (E) elementData[i];
if (filter.test(element)) {
//如果该元素需要被删除,将这个位置记录下来
removeSet.set(i);
removeCount++;
}
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
//通过要删除元素的个数是否>0来判断是否执行删除
final boolean anyToRemove = removeCount > 0;
if (anyToRemove) {
final int newSize = size - removeCount;
for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
//得到i的下一个不应该被删除的位置(包括i本身)
i = removeSet.nextClearBit(i);
elementData[j] = elementData[i];
}
//将后面的元素补充null
for (int k=newSize; k < size; k++) {
elementData[k] = null; // Let gc do its work
}
this.size = newSize;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
return anyToRemove;
}
//将list中的元素按照传进去的函数转换成另一个元素
@Override
@SuppressWarnings("unchecked")
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
elementData[i] = operator.apply((E) elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
//调用Arrays里面的方法去对内部数组排序
@Override
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
}