Когда я сортирую список, что происходит с его итераторами?

Скажем, у меня есть объект List и итератор для этого списка.

Сейчас сортирую список с java.util.Collections.sort()

  • Что происходит с итератором?
  • Его поведение все еще определено и можно ли его использовать?
  • Если нет, могу ли я предотвратить уничтожение итераторов для списка?

Я знаю, что эту проблему можно обойти, изменив дизайн программы, например, клонируя список, но я конкретно хочу знать «официальное» поведение Java.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
11
0
5 353
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Итераторы обычно недействительны после модификации Любые их базовых коллекций, за исключением самого итератора. (Например, ListIterator позволяет вставлять и удалять.)

Я бы определенно ожидал, что любые итераторы станут недействительными после сортировки - а если бы это было не так, я бы не знал, какой порядок ожидать.

Это ясный ответ для единственного итератора p, указывающего на коллекцию c. Как насчет того, чтобы два итератора p и q указывали на одну и ту же коллекцию c и повторялись независимо? Означает ли "кроме самого итератора" конкретный экземпляр итератора, например p, или любой экземпляр итератора? Я предполагаю, что независимая итерация p и q аннулирует друг друга (просто потому, что ни итераторы не знают о других итераторах, ни коллекция не запоминает все свои итераторы), но здесь полезно уточнить это. Спасибо!

uvsmtid 02.12.2016 05:43

@uvsmtid: кроме этого конкретного итератора. Если у вас есть два итератора для одной и той же коллекции, вы не можете изменить коллекцию через любой из них, если только это не коллекция, которая явно поддерживает одновременное изменение.

Jon Skeet 02.12.2016 09:30

Как правило, любые изменения в коллекции делают ее итераторы недействительными. Мутация, выполненная с помощью итератора, не сделает этот итератор недействительным. Есть несколько исключительных реализаций коллекций, например CopyOnWriteArrayList.

Общее решение - отсортировать копию коллекции или воссоздать итераторы.

Ответ принят как подходящий

Большинство коллекций в java.util работают без сбоев, и май генерирует ConcurrentModificationException, если базовая коллекция изменяется. Следует отметить, что это предназначено для отладки и поэтому не гарантируется. Согласно javadocs, это верно для всех потомков AbstractList, но это нет верно для CopyOnWriteArrayList, который предназначен для многопоточного использования.

Я написал код, чтобы увидеть, что происходит, когда коллекция сортируется во время итерации. Кажется, что итератор не генерирует никаких исключений, но продолжает нормально выполнять итерацию. Тем не менее, это дает неправильные результаты, если вы ожидаете перебирать несортированную коллекцию. Посмотри на это :

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

Надеюсь, это поможет.

Где "обычно" включает "может снова увидеть тот же элемент" ... Честно говоря, я немного разочарован тем, что это не вызывает исключения.

Jon Skeet 18.11.2008 19:24

Исключение не гарантируется, оно предназначено для отладки.

sblundy 18.11.2008 19:31

Другие вопросы по теме