Java 当我对列表排序时,它的迭代器会发生什么变化?

Java 当我对列表排序时,它的迭代器会发生什么变化?,java,collections,concurrency,Java,Collections,Concurrency,假设我有一个列表对象和一个该列表的迭代器 现在,我使用java.util.Collections.sort()对列表进行排序 迭代器会发生什么情况 其行为是否仍有定义,是否仍可以使用 如果没有,我可以防止销毁列表的迭代器吗 我知道,通过改变程序设计,例如克隆列表,可以避免这个问题,但我特别想知道Java的“官方”行为。迭代器在对其基础集合进行任何修改后通常无效,除非通过迭代器本身。(例如,允许插入和删除。) 不过,我当然希望任何迭代器在排序后都会失效——如果不是,我也不知道会出现什么顺序。通

假设我有一个列表对象和一个该列表的迭代器

现在,我使用
java.util.Collections.sort()对列表进行排序

  • 迭代器会发生什么情况
  • 其行为是否仍有定义,是否仍可以使用
  • 如果没有,我可以防止销毁列表的迭代器吗

我知道,通过改变程序设计,例如克隆列表,可以避免这个问题,但我特别想知道Java的“官方”行为。

迭代器在对其基础集合进行任何修改后通常无效,除非通过迭代器本身。(例如,允许插入和删除。)


不过,我当然希望任何迭代器在排序后都会失效——如果不是,我也不知道会出现什么顺序。

通常,集合上的任何类型的变异都会使其迭代器失效。通过迭代器进行的变异不会使迭代器失效。有一些特殊的集合实现,例如
CopyOnWriteArrayList


一般的解决方案是对集合的副本进行排序或重新创建迭代器。

java.util
中的大多数集合都是“快速失败的”,如果基础集合发生更改,可能会抛出一个错误。应该指出的是,这是为了调试,因此不能保证。根据javadocs,这适用于的所有死者,但这不适用于,它是用于多线程使用的

我编写了一些代码,以查看在迭代过程中对集合进行排序时会发生什么。迭代器似乎没有抛出任何异常,而是继续正常地进行迭代。但是,如果您希望在未排序的集合上进行迭代,那么它会给出错误的结果。看看这个:

public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("D");
    list.add("B");
    list.add("A");
    list.add("C");
    list.add("E");

    Iterator<String> it = list.iterator();
    String s = it.next();
    System.out.println(s);
    s = it.next();
    System.out.println(s);

    Collections.sort(list);
    Iterator<String> it2 = list.iterator();

    s = it.next();
    System.out.println(s);
    s = it.next();
    System.out.println(s);
    s = it.next();
    System.out.println(s);

    while (it2.hasNext()) {
        System.out.println(it2.next());
    }
    }
publicstaticvoidmain(字符串[]args){
列表=新的ArrayList();
列表。添加(“D”);
列表。添加(“B”);
列表。添加(“A”);
列表。添加(“C”);
列表。添加(“E”);
Iterator it=list.Iterator();
字符串s=it.next();
系统输出打印项次;
s=it.next();
系统输出打印项次;
集合。排序(列表);
迭代器it2=list.Iterator();
s=it.next();
系统输出打印项次;
s=it.next();
系统输出打印项次;
s=it.next();
系统输出打印项次;
while(it2.hasNext()){
System.out.println(it2.next());
}
}

希望有帮助。

其中“正常”包括“可能再次看到相同的元素”。。。老实说,我有点失望,这没有引发异常。异常不一定会引发,它是用于调试的。对于指向集合
c
的单个迭代器
p
来说,这是一个明确的答案。让两个迭代器
p
q
指向同一个集合
c
并独立迭代怎么样?“除了通过迭代器本身”是指迭代器的特定实例,比如
p
,还是指迭代器的任何实例?我猜
p
q
的独立迭代将使彼此无效(这仅仅是因为迭代器不知道其他迭代器,集合也不记得所有迭代器),但最好在这里澄清一下。谢谢@uvsmtid:除了通过特定的迭代器。如果在同一个集合上有两个迭代器,则不能通过它们中的任何一个修改集合,除非该集合明确支持并发修改。