ArrayList的subList会出现的异常

ArrayList的subList会出现的异常

【阿里巴巴手册规定】
在 subList 场景中, 高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生
ConcurrentModificationException 异常。

1、subList方法
理解:ArrayList 的方法 subList() 就是分割集合的一段出来使用
示例:

package com.song.list;

import java.util.ArrayList;
import java.util.List;

public class Sublist {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        //注意:(0,2) 是 左闭又开 取值 ,取的是索引对应的 0,1 两个元素 
        List<String> subList = list.subList(0, 2);

        //subList 即包含了元素 "aa"和"bb"
        for (String s : subList) {
            System.out.println(s);
        }
    }
}

错误示例:

 public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(5);
        arrayList.add(6);

        List<Integer> list = arrayList.subList(1, 3);

        for (Integer integer : list) {
            System.out.println(" "+integer);
        }

        System.out.println("wo modify arrayList");
        arrayList.remove(0);

        for (Integer integer : list) {
            System.out.println(" "+integer);
        }
    }

日志输出如下:
在这里插入图片描述
为什么会这样呢?
AbstractList

// 定义了一个modCount属性。
   protected transient int modCount = 0;

因为ArrayList的父类AbstractList中有个protected transient int modCount = 0;
modCount 的作用是用来记录当前ArrayList被修改的次数。
比如add(),remove()等都会导致modeCount增加

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; // clear to let GC do its work

        return oldValue;
    }

(1) SubList 继承 AbstractList ,所以具有List接口的所有方法。
(2) SubList 是ArrayList 的一个内部类。SubList并没有重新创建一个List,而是直接引用原有的List,只不过对原来List做截取而已。
(3) ArrayList 也是继承AbstractList,但是 SubList 和 ArrayList 没有继承关系,所以不能强制转换。

ArrayList.subList()会生成一个SubList的对象,SubList中有个对应modCount同步ArrayList中的modeCount:

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 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 class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
		
        protected transient int modCount = 0;
        ...
        public List<E> subList(int fromIndex, int toIndex) {
        
           subListRangeCheck(fromIndex, toIndex, size);
           return new SubList(this, 0, fromIndex, toIndex);
   			
         }

SubList对象每次再遍历时,会将自己的modeCount与ArrayList的modeCount进行对比,如果两个值不一样就会报异常:ConcurrentModificationException

 		
        public ListIterator<E> listIterator(final int index) {
            checkForComodification();
           ...
        }
       
		...
        private void checkForComodification() {
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
        }


总结:

1、subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList 而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

2、在 subList 场景中,高度注意对原集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值