2017-06-13 141 views
4

为什么发生?不清楚java.util.ConcurrentModificationException

我写了这个代码,它抛出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); 
+2

@Blasanka哪里第一代码片段迭代,同时做一些修改?你有没有看到,唯一的区别是两行交换,其中一行只打印子列表? – Seelenvirtuose

+0

我知道在列表迭代期间的修改。但以我的方式,我有两个单线程的最终操作 –

回答

4

在Javadoc中寻找的subList()方法,它明确指出:

如果 支持列表(即,此列表)是在结构上经过以任何方式 而非经由返回列表,则由此方法返回的列表的语义变得不明确。

在你的第一个例子,这正是发生了什么:你在结构上通过调用removeAll()修改后台列表,让您的子列表的行为是不确定现在。

事实上,随后的打印列表最终抛出ConcurrentModificationException只是一个实现细节。

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

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

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

0

谢谢Robby Cornelissen

接下来代码将修复

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