【Java集合类】ArrayList

方法

subList(int fromIndex, int toIndex)

可以看一下subList源码片段
在这里插入图片描述

public List<E> subList(int fromIndex, int toIndex) {
     subListRangeCheck(fromIndex, toIndex, size);
     return new SubList<>(this, fromIndex, toIndex);
 }
private static class SubList<E> extends AbstractList<E> implements RandomAccess{
...
}

可以看一下继承关系。
在这里插入图片描述
可以得到以下几个关键信息:

  1. subList返回的是一个SubList类型的对象
  2. 对原list和新list做非结构性修改都会影响到彼此
  3. 对原list做非结构性修改,会报错

验证:对原list和新list做非结构性修改都会影响到彼此

    public static void main(String[] args) {
        ArrayList old_list = new ArrayList();
        old_list.add("1"); old_list.add("1"); old_list.add("1"); old_list.add("1"); old_list.add("1");
        List new_list = old_list.subList(1, 3);
        System.out.println("原list = " + old_list.toString() + "新list = " + new_list.toString());
        
        old_list.set(2, "hh"); // 对原list进行非结构性修改
        System.out.println("原list = " + old_list.toString() + "新list = " + new_list.toString());
        
        new_list.set(0, "xx");// 对新list进行非结构性修改
        System.out.println("原list = " + old_list.toString() + "新list = " + new_list.toString());
    }

输出:

原list = [1, 1, 1, 1, 1]新list = [1, 1]
原list = [1, 1, hh, 1, 1]新list = [1, hh]
原list = [1, xx, hh, 1, 1]新list = [xx, hh]

验证:对原list做结构性修改,会报错

    public static void main(String[] args) {
        ArrayList old_list = new ArrayList();
        old_list.add("1"); old_list.add("1"); old_list.add("1"); old_list.add("1"); old_list.add("1");
        List new_list = old_list.subList(1, 3);
        System.out.println("原list = " + old_list.toString() + "新list = " + new_list.toString());
        old_list.add(5);
        System.out.println("原list = " + old_list.toString() + "新list = " + new_list.toString());
    }

输出:

原list = [1, 1, 1, 1, 1]新list = [1, 1]
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1415)
	at java.base/java.util.ArrayList$SubList.listIterator(ArrayList.java:1284)
	at java.base/java.util.AbstractList.listIterator(AbstractList.java:311)
	at java.base/java.util.ArrayList$SubList.iterator(ArrayList.java:1280)
	at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:449)
	at com.example.sprint_test01.TestArrayList.main(TestArrayList.java:22)

为什么呢?看一下源码,在jdk注释里有这么一段话:

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. 
(If fromIndex and toIndex are equal, the returned list is empty.) 
The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, 
and vice-versa. The returned list supports all of the optional list operations.

意思就是说,subList方法返回的是一个视图,可以理解为一个映射窗口,fromIndextoIndex理解为窗口的边界,我们就可以到这个边界内的元素,当内部元素改变的时候,我们看到的也就变了,理解为一个引用。

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList<>(this, fromIndex, toIndex);
    }

    private static class SubList<E> extends AbstractList<E> implements RandomAccess {
        private final ArrayList<E> root;
        private final SubList<E> parent;
        private final int offset;
        private int size;

        /**
         * Constructs a sublist of an arbitrary ArrayList.
         */
        public SubList(ArrayList<E> root, int fromIndex, int toIndex) {
            this.root = root;
            this.parent = null;
            this.offset = fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = root.modCount;
        }

        /**
         * Constructs a sublist of another SubList.
         */
        private SubList(SubList<E> parent, int fromIndex, int toIndex) {
            this.root = parent.root;
            this.parent = parent;
            this.offset = parent.offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = parent.modCount;
        }

可以看到,调用subList方法的时候,我们用的其实就是引用的原有的list,并规定了边界。
同时可以看到为什么subList得到的集合不能转换为ArrayList,因为SubList只是ArrayList的内部类,与其并没有继承关系。

  • 18
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值