java.util.ConcurrentModificationException背后的原因 Stack ST=new Stack(); ST.add(“一”); ST.add(“两”); 圣加达(“三”); 圣加达(“四”); ST.addAll(ST.subList(0,2)); 系统输出打印LN(ST);

java.util.ConcurrentModificationException背后的原因 Stack ST=new Stack(); ST.add(“一”); ST.add(“两”); 圣加达(“三”); 圣加达(“四”); ST.addAll(ST.subList(0,2)); 系统输出打印LN(ST);,java,exception,Java,Exception,下面的简单代码给出了java.util.ConcurrentModificationException。我不知道这个异常背后的原因是什么 List.subList将视图返回到容器中,而不是副本 从 如果 支持列表(即此列表)在结构上以任何方式进行修改 而不是通过返回的列表。(结构修改是指 改变这个列表的大小,或者以这种方式扰乱它 进行中的迭代可能产生错误结果的方式。) 因此,当您调用addAll时,它会修改底层容器并更改其大小,从而使子列表无效。但它仍在尝试迭代子列表以继续添加内容。问题发生在这

下面的简单代码给出了java.util.ConcurrentModificationException。我不知道这个异常背后的原因是什么

List.subList
将视图返回到容器中,而不是副本

如果 支持列表(即此列表)在结构上以任何方式进行修改 而不是通过返回的列表。(结构修改是指 改变这个列表的大小,或者以这种方式扰乱它 进行中的迭代可能产生错误结果的方式。)


因此,当您调用addAll时,它会修改底层容器并更改其大小,从而使子列表无效。但它仍在尝试迭代子列表以继续添加内容。

问题发生在这里:

Stack<String> ST = new Stack<String>();
ST.add("one");
ST.add("two");
ST.add("three");
ST.add("four");

ST.addAll(ST.subList(0,2));
System.out.println(ST);
问题是,在引擎盖下发生了以下事情:

  • ST.subList(0,2)
    调用为原始列表创建一个包装器

  • ST.addAll
    调用为子列表创建一个
    迭代器
    ,它实际上是原始列表的
    列表迭代器
    的包装器

  • 然后,在迭代子列表(以及列表)时,它将找到的元素推回到原始列表上

  • 最后一个是并发修改

    请注意,这是固有的,而不仅仅是实现细节。
    子列表
    方法返回原始
    列表的视图
    。因此,您的语句本质上是同时迭代和修改同一个(基础)列表。

    声明说:

    如果支持列表(即,此列表)以任何方式(而不是通过返回的列表)进行结构修改,则此方法返回的列表的语义将变得未定义。(结构修改是指改变列表大小,或以其他方式干扰列表,从而使正在进行的迭代可能产生错误结果的修改。)

    换句话说,在访问子列表时,不允许更改实际列表

    当你打电话的时候

    ST.addAll(ST.subList(0,2));
    
    您正在使
    addAll
    遍历子列表,同时修改实际列表(
    ST
    addAll
    将从子列表中获取第一个元素,并将其附加到
    ST
    ,这是一种结构修改,使基于
    ST
    的任何子列表无效。然后,
    addAll
    将尝试从子列表中获取第二个元素,但由于对
    ST
    所做的更改,子列表现在无效,因此它引发异常

    ST.addAll(ST.subList(0,2));