不清楚java.util.ConcurrentModificationException

时间:2017-06-13 06:59:37

标签: java

为什么会这样?

我已编写此代码并抛出 java.util.ConcurrentModificationException

List<Integer> list = Stream.iterate(0, t -> t + 1).limit(10).collect(Collectors.toList());
System.out.println(list);
List<Integer> subList = list.subList(5, list.size());
list.removeAll(subList);
System.out.println(subList);
System.out.println(list);

但下一个代码不会抛出

List<Integer> list = Stream.iterate(0, t -> t + 1).limit(10).collect(Collectors.toList());
System.out.println(list);
List<Integer> subList = list.subList(5, list.size());
System.out.println(subList);
list.removeAll(subList);
System.out.println(list);

3 个答案:

答案 0 :(得分:4)

查看subList()方法的Javadoc,它明确指出:

  

如果是,则此方法返回的列表的语义将变为未定义   支持列表(即,此列表)以任何方式结构修改   除了通过返回的列表。

在您的第一个示例中,这正是发生的事情:您通过调用removeAll()在结构上修改了支持列表,因此您的子列表的行为现在未指定。

打印列表的后续调用最终会抛出ConcurrentModificationException,这只是一个实现细节。

如果你想避免这种情况,你必须从你检索的子列表中创建一个新列表,即

List<Integer> subList = new ArrayList<>(list.subList(5, list.size()));
list.removeAll(subList);

现在可以独立访问和修改这两个列表。

答案 1 :(得分:0)

谢谢你,Robby Cornelissen

下一个代码将修复

    List<Integer> subList = new ArrayList<>(list.subList(5, list.size()));

答案 2 :(得分:0)

代替创建新列表,使用CopyOnWriteArrayList怎么办?

List<Integer> subList = new CopyOnWriteArrayList<>(list.subList(5, list.size()));