Collection集合06-ArrayList的sublist方法使用

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();
    }
}
  • 返回Iterator会校验modeCount
public ListIterator<E> listIterator(final int index) {
    checkForComodification();
    。。。。
}
private void checkForComodification() {
        if (ArrayList.this.modCount != this.modCount)
            throw new ConcurrentModificationException();
    }

subList的增删改查操作

  • 本质上也是对原list进行操作
     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的数组进行操作
posted @ 2023-08-30 14:27  PerfectLi  阅读(38)  评论(0编辑  收藏  举报