子列表抛出的ConcurrentModificationException
我的代码非常简单:
List list = new ArrayList(); String a = "a"; String b = "b"; String c = "c"; String d = "d"; list.add(a); list.add(b); list.add(c); List backedList = list.subList(0, 2); list.add(0, d); System.out.println("2b: " + backedList);
我通过list.add(0,d)得到ConcurrentModificationExceptionexception。 所以一般来说,这是因为sublist()。 我很困惑,因为在sublist()的情况下,文档说:
返回的列表由此列表支持,因此返回列表中的非结构更改将反映在此列表中, 反之亦然 。
你能解释一下捕获的位置吗?
subList
是原始列表的简单视图(参见此处 )。 您可以改变其中的元素,但不能更改列表的结构。
根据文档,如果您尝试进行结构更改,则未定义子subList
行为。 我想在这个特定的实现中, ConcurrentModificationException
被确定为未定义的行为。
如果支持列表(即此列表)在结构上以除返回列表之外的任何方式进行修改,则此方法返回的列表的语义将变为未定义。 (结构修改是那些改变了这个列表的大小,或以其他方式扰乱它的方式,正在进行的迭代可能会产生不正确的结果。)
返回的列表由此列表支持,因此返回列表中的非结构更改将反映在此列表中,反之亦然。 参考链接
上述陈述绝对正确,但我们必须牢记非结构性变化。 我想描述两个certificate上述陈述的例子。
示例1:在列表中执行非结构更改。
public static void main(String[] args) { List listArr = new ArrayList<>(); listArr.add("Delhi"); listArr.add("Bangalore"); listArr.add("New York"); listArr.add("London"); List listArrSub = listArr.subList(1, 3); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); //Performing Non-Structural Change in list. Collections.swap(listArr, 0, 1); System.out.println("\nAfter Non-Structural Change...\n"); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); }
输出 – :
List-: [Delhi, Bangalore, New York, London] Sub List-: [Bangalore, New York] After Non-Structural Change... List-: [Bangalore, Delhi, New York, London] Sub List-: [Delhi, New York]
说明 – :根据上述Oracle的文档声明,交换操作反映在两个列表中。
示例2:在子列表中执行非结构更改。
public static void main(String[] args) { List listArr = new ArrayList<>(); listArr.add("Delhi"); listArr.add("Bangalore"); listArr.add("New York"); listArr.add("London"); List listArrSub = listArr.subList(1, 3); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); //Performing Non-Structural Change in sub list. Collections.swap(listArrSub, 0, 1); System.out.println("\nAfter Non-Structural Change...\n"); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); }
输出 – :
List-: [Delhi, Bangalore, New York, London] Sub List-: [Bangalore, New York] After Non-Structural Change... List-: [Delhi, New York, Bangalore, London] Sub List-: [New York, Bangalore]
说明 – :根据上述Oracle的文档声明,交换操作反映在两个列表中,但它已在子列表上执行。
正如我们在上述两个例子中看到的非结构变化。 现在让我们看一下根据Oracle文档中给出的以下语句的结构变化。
如果支持列表(即此列表)在结构上以除返回列表之外的任何方式进行修改,则此方法返回的列表的语义将变为未定义。 (结构修改是那些改变了这个列表的大小,或以其他方式扰乱它的方式,正在进行的迭代可能会产生不正确的结果。)
示例3:在列表中执行结构更改。
public static void main(String[] args) { List listArr = new ArrayList<>(); listArr.add("Delhi"); listArr.add("Bangalore"); listArr.add("New York"); listArr.add("London"); List listArrSub = listArr.subList(1, 3); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); //Performing Structural Change in list. listArr.add("Mumbai"); System.out.println("\nAfter Structural Change...\n"); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); }
输出 – :
List-: [Delhi, Bangalore, New York, London] Sub List-: [Bangalore, New York] After Structural Change... List-: [Delhi, Bangalore, New York, London, Mumbai] Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231) at java.util.ArrayList$SubList.listIterator(ArrayList.java:1091) at java.util.AbstractList.listIterator(AbstractList.java:299) at java.util.ArrayList$SubList.iterator(ArrayList.java:1087) at java.util.AbstractCollection.toString(AbstractCollection.java:454) at java.lang.String.valueOf(String.java:2982) at java.lang.StringBuilder.append(StringBuilder.java:131) at infosys.Research.main(Research.java:26)
解释 – :根据上述Oracle的文档声明,结构修改操作每当抛出此方法返回的列表的语义变为未定义时,如果支持列表(即此列表)在结构上以任何其他方式修改,则抛出java.util.ConcurrentModificationException
exception而不是通过返回的列表。
示例4:在子列表中执行结构更改。
public static void main(String[] args) { List listArr = new ArrayList<>(); listArr.add("Delhi"); listArr.add("Bangalore"); listArr.add("New York"); listArr.add("London"); List listArrSub = listArr.subList(1, 3); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); //Performing Structural Change in sub list. listArrSub.add("Mumbai"); System.out.println("\nAfter Structural Change...\n"); System.out.println("List-: " + listArr); System.out.println("Sub List-: " + listArrSub); }
输出 – :
List-: [Delhi, Bangalore, New York, London] Sub List-: [Bangalore, New York] After Structural Change... List-: [Delhi, Bangalore, New York, Mumbai, London] Sub List-: [Bangalore, New York, Mumbai]
说明 – 对返回列表的结构修改运行良好,并完全反映在列表中。
list.add(0,d)涉及将所有项目移动一个位置并增加列表的大小。 这是相当结构性的变化。
遇到此错误的情况
- 我有一个列表(原始列表),让我们说100项
- 按升序对原始列表进行排序
- 子列表 – >创建子列表(升序有序子列表)
- 按降序对原始列表进行排序
- 迭代子列表(升序有序子列表)列表
得到并发修改exception
修复上述情况
- 我有一个列表(原始列表),让我们说100项
- 按升序排序
- 子列表 – >创建子列表(升序有序子列表)
- 迭代下载(升序有序子列表)列表
- 按降序对原始列表进行排序