子列表抛出的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.ConcurrentModificationExceptionexception而不是通过返回的列表。

示例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项
  • 按升序排序
  • 子列表 – >创建子列表(升序有序子列表)
  • 迭代下载(升序有序子列表)列表
  • 按降序对原始列表进行排序