为什么并发修改会出现在这里
Why the concurrent modification comes here
以下代码抛出并发修改异常
import java.util.*;
public class SampleTest
{
public static void main(String[] args) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("value1","a");
map.put("value2","b");
map.put("value3","c");
map.put("value4","d");
map.put("value5","e");
// sublists
List<LinkedHashMap<String, String>> subList = new ArrayList<>();
for(int i = 0; i<5; i++) {
subList.add(map);
}
List<List<LinkedHashMap<String, String>>> mainList = new LinkedList<>();
for(int i = 0; i<3; i++)
{
mainList.add(subList);
}
List<LinkedHashMap<String,String>> temp = mainList.get(mainList.size() - 1);
List<LinkedHashMap<String,String>> temp2 = mainList.get(mainList.size() - 2);
for(LinkedHashMap<String,String> map2 : temp) {
temp2.add(map); // Exception Thrown Here......
}
}
}
但是我通过创建一个新列表并添加地图修复了代码,最后在 temp2 的循环外添加了新列表
example,
List<LinkedHashMap<String,String>> pp = new ArrayList<>();
for(LinkedHashMap<String,String> map2 : temp) {
pp.add(map);
}
temp2.addAll(pp);
我想详细了解为什么在前面的代码中会出现并发。
谢谢。
此代码:
List<List<LinkedHashMap<String, String>>> mainList = new LinkedList<>();
for(int i = 0; i<3; i++)
{
mainList.add(subList);
}
正在将 subList
添加到 mainList
三次。当我说 "three times" 时,我的意思是代码实际上是将 同一实例 添加了三次。您可以修改 mainList
的任何有效索引处的元素,并且您将修改所有其他元素,因为它们是相同的实例。参见this question;它可能有助于这个概念。
因此,此代码:
List<LinkedHashMap<String,String>> temp = mainList.get(mainList.size() - 1);
List<LinkedHashMap<String,String>> temp2 = mainList.get(mainList.size() - 2);
从两个不同的索引中抓取 same List
并将其分配给两个不同的变量。换句话说,temp == temp2
(引用相等)是true
.
然后使用 temp
变量迭代 List
,同时使用 temp2
变量向 List
添加元素:
for(LinkedHashMap<String,String> map2 : temp) {
temp2.add(map); // Exception Thrown Here......
}
但同样,temp
和 temp2
指的是 相同的 List
。您的代码基本上执行以下操作:
List<Object> list = ...; // create new list and fill it
Object someObj = new Object();
for (Object obj : list) { // iterating list
list.add(someObj); // modifying list while it's being iterated
}
最终结果是您在迭代 List
的同时尝试修改它。 LinkedList
(或者 Collection
的任何标准实现)都不允许这样做。来自 documentation:
The iterators returned by this class's iterator
and listIterator
methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the Iterator's own remove
or add
methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
如果您不知道,当循环的目标是 Iterable
.
时,for-each 循环在内部使用 Iterator
以下代码抛出并发修改异常
import java.util.*;
public class SampleTest
{
public static void main(String[] args) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("value1","a");
map.put("value2","b");
map.put("value3","c");
map.put("value4","d");
map.put("value5","e");
// sublists
List<LinkedHashMap<String, String>> subList = new ArrayList<>();
for(int i = 0; i<5; i++) {
subList.add(map);
}
List<List<LinkedHashMap<String, String>>> mainList = new LinkedList<>();
for(int i = 0; i<3; i++)
{
mainList.add(subList);
}
List<LinkedHashMap<String,String>> temp = mainList.get(mainList.size() - 1);
List<LinkedHashMap<String,String>> temp2 = mainList.get(mainList.size() - 2);
for(LinkedHashMap<String,String> map2 : temp) {
temp2.add(map); // Exception Thrown Here......
}
}
}
但是我通过创建一个新列表并添加地图修复了代码,最后在 temp2 的循环外添加了新列表
example,
List<LinkedHashMap<String,String>> pp = new ArrayList<>();
for(LinkedHashMap<String,String> map2 : temp) {
pp.add(map);
}
temp2.addAll(pp);
我想详细了解为什么在前面的代码中会出现并发。
谢谢。
此代码:
List<List<LinkedHashMap<String, String>>> mainList = new LinkedList<>();
for(int i = 0; i<3; i++)
{
mainList.add(subList);
}
正在将 subList
添加到 mainList
三次。当我说 "three times" 时,我的意思是代码实际上是将 同一实例 添加了三次。您可以修改 mainList
的任何有效索引处的元素,并且您将修改所有其他元素,因为它们是相同的实例。参见this question;它可能有助于这个概念。
因此,此代码:
List<LinkedHashMap<String,String>> temp = mainList.get(mainList.size() - 1);
List<LinkedHashMap<String,String>> temp2 = mainList.get(mainList.size() - 2);
从两个不同的索引中抓取 same List
并将其分配给两个不同的变量。换句话说,temp == temp2
(引用相等)是true
.
然后使用 temp
变量迭代 List
,同时使用 temp2
变量向 List
添加元素:
for(LinkedHashMap<String,String> map2 : temp) {
temp2.add(map); // Exception Thrown Here......
}
但同样,temp
和 temp2
指的是 相同的 List
。您的代码基本上执行以下操作:
List<Object> list = ...; // create new list and fill it
Object someObj = new Object();
for (Object obj : list) { // iterating list
list.add(someObj); // modifying list while it's being iterated
}
最终结果是您在迭代 List
的同时尝试修改它。 LinkedList
(或者 Collection
的任何标准实现)都不允许这样做。来自 documentation:
The iterators returned by this class's
iterator
andlistIterator
methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the Iterator's ownremove
oradd
methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
如果您不知道,当循环的目标是 Iterable
.
Iterator