2017-06-13 140 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()));