Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么列表的反转子列表的List.addAll会导致ConcurrentModificationException_Java_Arraylist_Collections_Concurrentmodification - Fatal编程技术网

Java 为什么列表的反转子列表的List.addAll会导致ConcurrentModificationException

Java 为什么列表的反转子列表的List.addAll会导致ConcurrentModificationException,java,arraylist,collections,concurrentmodification,Java,Arraylist,Collections,Concurrentmodification,我一直在尝试对一个列表进行排序,将其反转,然后将列表放回起始位置。例如,假设我们有一个列表[1,2,3,4,5,6],那么从索引2倒回到索引4将得到[1,2,5,4,3,6] 我已经为此编写了一些代码,但是每次它都会给出一个ConcurrentModificationException(除非startIndex==endIndex)。下面提供了一个最小可复制示例: int startIndex = 2; int endIndex = 4; List<Integer> list = n

我一直在尝试对一个列表进行排序,将其反转,然后将列表放回起始位置。例如,假设我们有一个列表
[1,2,3,4,5,6]
,那么从索引2倒回到索引4将得到
[1,2,5,4,3,6]

我已经为此编写了一些代码,但是每次它都会给出一个
ConcurrentModificationException
(除非startIndex==endIndex)。下面提供了一个最小可复制示例:

int startIndex = 2;
int endIndex = 4;
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);

List<Integer> toReverse = list.subList(startIndex, endIndex+1);
Collections.reverse(toReverse);
list.removeAll(toReverse);
list.addAll(startIndex, toReverse);
intstartindex=2;
int-endIndex=4;
列表=新的ArrayList();
增加第(1)款;
增加(2);
增加(3);
增加(4);
增加(5);
增加(6);
List toReverse=List.subList(开始索引,结束索引+1);
收藏。反向(反向);
list.removeAll(toReverse);
list.addAll(startIndex,toReverse);
线程“main”java.util.ConcurrentModificationException中出现异常
在java.util.ArrayList$SubList.checkForComodification(未知源)
位于
java.util.AbstractCollection.toArray(未知源代码)位于
位于
main(ConcurrentExample.java:64)

错误所指的实际行是
list.addAll(startIndex,toReverse)


我不确定问题是什么,因为在迭代过程中似乎没有任何内容得到更改。如果有人能解释为什么会发生这种情况和/或如何解决它,我们将不胜感激。

根据helosparkNir Levy的建议,在流中使用

List<Integer> toReverse = list.stream() //
                .skip(startIndex) //
                .limit(endIndex + 1) //
                .collect(Collectors.toList());
List-toReverse=List.stream()//
.skip(startIndex)//
.限制(endIndex+1)//
.collect(Collectors.toList());

List.subList返回指定元素之间列表的实时视图,而不是这些元素的副本(请参阅),因此添加到原始列表也会修改子列表,这将导致
ConcurrentModificationException
(因为添加的内容和添加到的内容也会同时被修改)

您可以通过复制列表来修复代码,如

List<Integer> toReverse = new ArrayList<>(list.subList(startIndex, endIndex+1));
List-toReverse=newarraylist(List.subList(startIndex,endIndex+1));
来自以下文件:

返回的列表由该列表支持,因此 返回的列表反映在此列表中,反之亦然


因此,当您尝试在子列表“视图”的索引处添加项目时,它会创建并发修改。

问题在于
ArrayList\checkForComodification

private void checkForComodification() {
    if (ArrayList.this.modCount != this.modCount)
        throw new ConcurrentModificationException();
    }
}
但是,在这种特殊情况下,您不需要手动重新添加反转子列表,因为反转是在原始列表上执行的。所以你所需要的就是放弃

list.removeAll(...);
list.addAll(...);
只保留以下代码:

List<Integer> toReverse = list.subList(startIndex, endIndex+1);
Collections.reverse(toReverse);
List-to-reverse=List.subList(开始索引,结束索引+1);
收藏。反向(反向);

@pvpkiran我认为这不是我的问题。我没有显式地使用任何迭代器(尽管我确信
reverse
隐式地使用一个迭代器来反转顺序)。在每个步骤结束后(如中,而不是在迭代过程中)所做的任何更改都是一致的,因为这一行:-list.removeAll(toReverse)。在调试器中查看reverseSee的值还可以查看您是否知道
子列表
将视图返回到原始列表中?当你做了
Collections.reverse(反向)时,您已经修改了原始列表;随后的
list.removeAll(toReverse);list.addAll(startIndex,toReverse)已完全过时。不需要副本。正如您自己所说,子列表是一个视图,因此在
Collections.reverse(toReverse)之后,原始列表已经修改,因此简单的修复方法是删除过时的
列表;list.addAll(startIndex,toReverse)语句。
List<Integer> toReverse = list.subList(startIndex, endIndex+1);
Collections.reverse(toReverse);