ArrayList的另外两个内部类
一、subList(int fromIndex, int toIndex)
//返回此列表中指定的fromIndex (包含)和toIndex (不包含)之间的部分的视图
public List<E> subList(int fromIndex, int toIndex) {
//判断参数的合法性
subListRangeCheck(fromIndex, toIndex, size);
//返回一个subList实例
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 + ")");
}
/*
* SubList返回的视图是由父类集合支持的,因此是非结构化的
* 所以,对SubList子集合进行操作,也会修改父类的集合。
* SubList类中,每个public方法(除了subList()方法)都调用checkForComodification()
* 用于判断父类集合是否被修改
* 所以,如果直接使用父类方法修改集合,则SubList子类的遍历、增加、删除等操作都会抛出异常
*
* SubList 内部类,继承了 AbstractList 类,并实现了 RandomAccess 接口,支持随机读取
*/
private class SubList extends AbstractList<E> implements RandomAccess {
// 父类的引用
private final AbstractList<E> parent;
//父类集合中的位置,如果使用SubList中的subList方法,
//则此时父类为SubList类,不是ArrayList
private final int parentOffset;
// 子类List在父类 ArrayList 中的下标位置
private final int offset;
// 视图集合的size
int size;
//构造方法
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
/触发快速失败机制的关键
this.modCount = ArrayList.this.modCount;
}
public E set(int index, E e) {
//传入参数索引合法性的检查
rangeCheck(index);
// 这个方法就是用来检验modCount从而触发fail-fast机制,
// 但是set这里modCount不会发生变化,所以不会触发fial-fast机制
checkForComodification();
// 从外部类(源列表)获取值
E oldValue = ArrayList.this.elementData(offset + index);
// 将外部类(源列表)的值替换成新的值,ArrayList的值是存在elementData的数组中的。
// 调用父类方法替换元素,所以本质上还是在父类集合中替换元素
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
//从上面代码看出,修改subList的值其实是在修改源列表的值的,
//所以源列表值发生变化是必然的。
//代码中调用的是list.add而不是subList.add
//也就是说我们没有再对SubList进行操作,SubList中的modCount也没有发生改变,
//所有 ArrayList.this.modCount != this.modCount 成立,导致抛出了ConcurrentModificationException异常。
//这里不仅打印会抛出异常,只要对subList进行操作都会抛出,因为SubList的方法都进行了checkForComodificatio,检查这两个modCount。
public E get(int index) {
//传入参数索引合法性的检查
rangeCheck(index);
// 这个方法就是用来检验modCount从而触发fail-fast机制,
// 但是set这里modCount不会发生变化,所以不会触发fial-fast机制
checkForComodification();
// 从外部类(源列表)获取值
return ArrayList.this.elementData(offset + index);
}
public int size() {
//检查modCount是否发生变化
checkForComodification();
return this.size;
}
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
// 使用父类方法添加元素,下标位置为parentOffset + index, 在父类集合添加元素。
parent.add(parentOffset + index, e);
// 父类add()方法修改了modCount的值,更新subList的modCount值
this.modCount = parent.modCount;
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;
}
public boolean addAll(Collection<? extends E> c) {
return addAll(this.size, 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 中迭代器使用ListIterator()
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
final int offset = this.offset;
return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = ArrayList.this.modCount;
public boolean hasNext() {
return cursor != SubList.this.size;
}
@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();
}
};
}
// 内部方法
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, offset, fromIndex, toIndex);
}
// 下标越界检查
private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
// 下标越界检查,仅add()方法和addAll()方法使用
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;
}
// 是否有多线程修改集合
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
public Spliterator<E> spliterator() {
checkForComodification();
return new ArrayListSpliterator<E>(ArrayList.this, offset,
offset + this.size, this.modCount);
}
}
注意事项:
①subList方法传入的参数是左闭右开的,也就是[formIndex,toIndex)的形式。所以如果传来两个相同的index进去会返回一个空的列表。
②subList方法返回的只是一个视图,是一个对源列表的映射。这意味着如果对subList返回的列表进行编辑操作,源列表也会收到影响。
③对subList方法返回的列表进行添加、删除元素会抛出异常。
④如果只对subList方法返回的列表:subList进行增删元素的操作,并不会抛出异常,但是同样会影响源列表,因为subList的所有操作都是在操作源列表。
二、spliterator()
@Override
public Spliterator<E> spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, 0);
}
static final class ArrayListSpliterator<E> implements Spliterator<E> {
// 存放ArrayList对象
private final ArrayList<E> list;
// 起始位置(包含)
private int index; // current index, modified on advance/split
// 结束位置(不包含)
private int fence; // -1 until used; then one past last index
// 存放list的modCount
private int expectedModCount; // initialized when fence set
/** Create new spliterator covering the given range */
ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list; // OK if null unless traversed
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
// 获取结束位置,用于初始化
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
ArrayList<E> lst;
// fence<0时(第一次初始化时,fence才会小于0)
if ((hi = fence) < 0) {
if ((lst = list) == null)
// list为null时,fence=0
hi = fence = 0;
else {
// list不为null时,fence=list的长度
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}
// 分割list,返回一个新分割出的spliterator实例
public ArrayListSpliterator<E> trySplit() {
// hi为结束位置,lo为起始位置,mid为中间值
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
// 当lo>=mid,表示不能在分割,返回null
// 当lo<mid,以mid分割,同时更新index。返回的是list前半部分,当前对象保留后半部分
return (lo >= mid) ? null : // divide range in half unless too small
new ArrayListSpliterator<E>(list, lo, index = mid,
expectedModCount);
}
// 返回true 时,只表示可能还有元素未处理
// 返回false 时,没有剩余元素处理了。。
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
// hi是结束位置,i是起始位置
int hi = getFence(), i = index;
if (i < hi) {
// 处理i位置元素,index+1
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)list.elementData[i];
// 调用action.accept处理元素
action.accept(e);
if (list.modCount != expectedModCount)
// 遍历时,多线程操作结构发生变更,抛出异常
throw new ConcurrentModificationException();
return true;
}
return false;
}
// 顺序处理元素
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) {
// 当fence<0时,进行初始化操作
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处理元素
action.accept(e);
}
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
// 估算大小
public long estimateSize() {
return (long) (getFence() - index);
}
public int characteristics() {
// 返回特征值
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
总结
ArrayListSpliterator:ArrayList可分割的迭代器,基于二分法的可分割迭代器,是为了并行遍历元素而设计的一种迭代器,jdk1.8 中的集合框架中的数据结构都默认实现了 spliterator。
Itr:实现Iterator接口的迭代器,为ArrayList进行优化。
ListItr:实现ListIterator接口的迭代器,为ArrayList进行优化。
SubList:实现了AbstractList和RandomAccess接口的子列表。(为了处理局部列表而设计的子列表类)