ArrayList的sublist方法
- 返回的是创建的List的内部类SubList的对象
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, this.size);
return new ArrayList.SubList(this, fromIndex, toIndex);
}
SubList
- 本质时List对象的一个视图,没有生成新的List
- 创建一个内部类SubList,返回的是List类型的集合,而不是ArrayList
- 这个toIndex,决定的只是从起始index后所截取的长度
private static class SubList<E> extends AbstractList<E> implements RandomAccess{
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;// offset //默认是0,相当于其实的位置变成了 0+ fromIndex
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
- Iterator遍历元素
- 获取原List的内部数组Element
- 从Sublist创建时配置的偏移量offset开始遍历
- 遍历的长度是时计算的size
- 在iterator之前会进行modeCount的校验,这也就说明,在获取subList和操作subList之间不能对原有的ArrayList对象进行增删操作
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)];
}
- 增删改查操作
- 增删改查操作的时候都会校验操作的modeCount
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();//校验modeCount
parent.add(parentOffset + index, e);//是在起始位置上进行增
this.modCount = parent.modCount;
this.size++;
}
private void checkForComodification() {
if (this.root.modCount != this.modCount) {
throw new ConcurrentModificationException();
}
}
public ListIterator<E> listIterator(final int index) {
checkForComodification();
。。。。
}
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
subList的增删改查操作
public E remove(int index) {
Objects.checkIndex(index, this.size);
this.checkForComodification();
E result = this.root.remove(this.offset + index);
this.updateSizeAndModCount(-1);
return result;
}
测试代码
ArrayList<String> list = new ArrayList<>();
list.add("a0");
list.add("a1");
list.add("a2");
list.add("a3");
list.add("a4");
// List<String> temp = list.stream().skip(0).limit(5).collect(Collectors.toList());
// System.out.println(temp);
List<String> temp = list.subList(2, 5);
list.add("w1");//只要原list进行了操作,temp再进行操作时就会出现异常
temp.add("a6");
System.out.println(temp);
总结
- Sublist是ArrayList原list的视图并不是生成新的ArrayList,而是SubList的List
- 原list进行增删操作,会让Sublist的操作报错ConcurrentModificationException
- Sublist进行增删改查,直接对原list的数组进行操作