为什么并发修改会出现在这里

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......
}

但同样,temptemp2 指的是 相同的 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