Java Collections.sort() 缺少 ConcurrentModificationException

标签 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);
    }

输出

List: 2,1,
CurrentElement: 2
List: 1,2,
CurrentElement: 2

人们会期待一个 ConcurrentModificationException,但它没有被引发并且代码有效,尽管它不应该。

最佳答案

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

请注意,ConcurrentModificationException 只会在迭代时将新元素添加到您的集合或从您的集合中移除时发生。即,当您的 Collections 被结构修改时。

(Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.)

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

for(Integer num : my_list) {
    my_list.add(12);
    }

如果你查看 Collections 中排序方法的源代码类,它不会抛出 ConcurrentModificationException

This implementation dumps the specified list into an array, sorts the array, and iterates over the list resetting each element from the corresponding position in the array. This avoids the n2 log(n) performance that would result from attempting to sort a linked list in place.

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]);
        }
    }

摘自本书java Generics and Collections :

The policy of the iterators for the Java 2 collections is to fail fast, as described in Section 11.1: every time they access the backing collection, they check it for structural modification (which, in general, means that elements have been added or removed from the collection). If they detect structural modification, they fail immediately, throwing ConcurrentModificationException rather than continuing to attempt to iterate over the modified collection with unpredictable results.

关于Java Collections.sort() 缺少 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13830309/

相关文章:

ruby - ruby 集合/可枚举的炫酷技巧和富有表现力的片段

java - 我需要 ByteArrayInputStream 的读取缓冲区吗

java - Oracle JDBC : underflow in double

java - 将单击监听器添加到 Drag-Sort-Listview 库

java - 如何在 NotesDocument 中存储 JDBC 服务器、数据库、用户名和密码

php - 如何根据值的实例数对数组进行排序?

actionscript-3 - 对 AS3 ByteArray 进行排序

java - 排序列表后,如何将列表中的对象取回它们原来的位置?

python - 我的程序正确执行所有操作,但它以随机顺序打印输入 [Python 3,初学者]

java - Java TreeMap put() 方法的奇怪行为