Java Collections.sort()缺少ConcurrentModificationException

Dan*_*iel 7 java sorting collections

我偶然发现了这个奇怪的错误.似乎Collections.sort()不会修改排序列表,以便在同时迭代同一列表时检测并发修改.示例代码:

    List<Integer> my_list = new ArrayList<Integer>();

    my_list.add(2);
    my_list.add(1);

    for (Integer num : my_list) {

        /*
         * print list
         */
        StringBuilder sb = new StringBuilder();
        for (Integer i : my_list)
            sb.append(i).append(",");
        System.out.println("List: " + sb.toString());

        /*
         * sort list
         */
        System.out.println("CurrentElement: " + num);
        Collections.sort(my_list);
    }
Run Code Online (Sandbox Code Playgroud)

输出

List: 2,1,
CurrentElement: 2
List: 1,2,
CurrentElement: 2
Run Code Online (Sandbox Code Playgroud)

人们会期望a ConcurrentModificationException,但它没有被提升,代码可以工作,尽管它不应该.

Per*_*ror 4

更新:这个答案是为 Java 6 编写的。随着JDK 8u20 的 Collection.sort 现在推迟到 List.sort,Java 8+ 现在确实会抛出异常,尽管正如 Brian Roach 所指出的,它仍然没有提供任何保证影响。

ConcurrentModificationException当您在迭代时不从集合中添加/删除元素时,为什么会抛出异常?

请注意,ConcurrentModificationException只有在迭代时将新元素添加到集合中或从集合中删除时,才会发生这种情况。即,当您的集合在结构上进行了修改时。

(结构修改是那些改变此列表大小的修改,或者以其他方式扰乱它,以致正在进行的迭代可能会产生不正确的结果。)

sort 不会在结构上修改您的集合,它所做的只是修改顺序。下面的代码会抛出异常ConcurrentModificationException,因为它在迭代时向集合中添加了一个额外的元素。

for(Integer num : my_list) {
    my_list.add(12);
    }
Run Code Online (Sandbox Code Playgroud)

如果您查看Collectionssort类中该方法的源代码,它不会抛出。ConcurrentModificationException

此实现将指定的列表转储到数组中,对数组进行排序,然后迭代列表,从数组中的相应位置重置每个元素。这避免了因尝试对链表进行就地排序而导致的 n2 log(n) 性能。

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]);
        }
    }
Run Code Online (Sandbox Code Playgroud)

摘自《java泛型和集合》一书:

Java 2 集合的迭代器的策略是快速失败,如第 11.1 节中所述:每次访问后备集合时,它们都会检查它的结构修改(这通常意味着元素已添加或删除)集合)。如果它们检测到结构修改,它们会立即失败,抛出 ConcurrentModificationException,而不是继续尝试迭代修改后的集合,结果不可预测。