在JDK1.6中對於一個集合進行迭代(hasNext)的過程當中,對這個集合進行動態的add或remove,程序會拋出ConcurrentModificationException的異常;可是,在迭代的過程當中對這個集合進行sort排序,程序不會發生異常。java
在JDK1.8中,除了迭代過程當中add或remove這個集合會ConcurrentModificationException;若是迭代過程當中對這個集合進行sort排序,也會ConcurrentModificationException。ide
這個行爲可能引起:在JDK1.6上執行不報錯的代碼,在JDK1.8上出現ConcurrentModificationException的報錯。spa
示例代碼:.net
package com.lands.concurrent;翻譯
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Vector;排序
public class ConcurrentModificationExceptionTest {ci
public static void main(String[] args) {
//when iterator, add or remove orignal colleciton.
//1.6.0_31 throws ConcurrentModificationException.
//1.8.0_92 throws ConcurrentModificationException.
//test1();element
//when iterator, sort orignal colleciton.
//1.6.0_31 correct.
//1.8.0_92 Both collections.sort and List.sort throws ConcurrentModificationException.
test2();rem
}文檔
private static void test1() {
Vector list = new Vector();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
Iterator itor = list.iterator();
while (itor.hasNext()) {
String temp = (String) itor.next();
System.out.println(temp);
if (temp.equals("c"))
list.add("g");
//list.remove("e");
}
}
private static void test2() {
Vector list = new Vector();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
Iterator itor = list.iterator();
while (itor.hasNext()) {
String temp = (String) itor.next();
System.out.println(temp);
if (temp.equals("c"))
Collections.sort(list);
// list.sort(new Comparator(){
// @Override
// public int compare(Object o1, Object o2) {
// return 0;
// }
// });
}
}
}
從Oracle官方,已經能夠看到這個問題的報告,但官方的態度是「Not an issue」(不是問題,不修復)。根據API文檔對於Iterator的行爲是這樣定義的「... The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way ... 」,翻譯過來就是「...在迭代的過程當中對底層集合進行任何形式的編輯,將致使集合迭代行爲的不肯定性...」。因此,若是之前在JDK1.8以前,可能運行正常的「迭代過程當中排序」的代碼,是一種並不規範的寫法。
Oracle Bugs的幾個報告連接:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6687277
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8157645
JDK1.6 vs JDK1.8的sort代碼的變化:
JDK1.6 - Collections.sort(list)邏輯。
public static <T extends Comparable<? super T>> void sort(List<T> list) {
Object[] a = list.toArray();
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
JDK1.8 - Collections.sort(list)邏輯。
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
@SuppressWarnings("unchecked")
@Override
public synchronized void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, elementCount, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++; --此句是重點,sort會改變modCount。當本次迭代經過以後,下一個迭代進來時,必然致使「modCount != expectedModCount」,拋出ConcurrentModificationException。 }