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
,但它没有被提升,代码可以工作,尽管它不应该.
更新:这个答案是为 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 2 集合的迭代器的策略是快速失败,如第 11.1 节中所述:每次访问后备集合时,它们都会检查它的结构修改(这通常意味着元素已添加或删除)集合)。如果它们检测到结构修改,它们会立即失败,抛出 ConcurrentModificationException,而不是继续尝试迭代修改后的集合,结果不可预测。
归档时间: |
|
查看次数: |
3224 次 |
最近记录: |