Параллельная модификация Java ArrayList - PullRequest
0 голосов
/ 06 ноября 2011

У меня возникают некоторые проблемы, чтобы получить эту работу хорошо, поскольку я аспект:

    for(Iterator<Object> i = mylist.iterator(); i.hasNext();) {
        Object obj = i.next();
        ArrayList<Object> newlist = new ArrayList<Object>();
        newlist.add(obj);
        i.remove();
        for(Iterator<Object> in = mylist.iterator(); in.hasNext();) {
            Object next = in.next();
            if (obj != next && (another condition)) {
                newlist.add(next);
                in.remove();
            }
        }
        if (newlist.size() > 2) anotheList.add(newlist);
        else for(Object r : newlist) {
            //mylist get back object:
            mylist.add(r);
        }
    }

Я пытаюсь найти элегантный способ сделать это без копирования mylist все больше и больше раз ...

Ответы [ 2 ]

6 голосов
/ 06 ноября 2011

То, что код в настоящее время делает, это:

  • В первой итерации внешнего цикла:
    • Удалить первый элемент.
    • В первом внутреннем цикле удалите все остальные элементы, которые не равны '==' первому элементу (который мы только что удалили)
    • Если мы удалили более 2 элементов, поместите их все в другое место.
    • В противном случае вернуть элемент в конец списка.

Очевидно, что это приводит к одновременной модификации на второй итерации внешнего цикла, поскольку внутренние циклы изменили коллекцию, которую вы повторяете во внешнем цикле. Вы не можете этого сделать.

Но, что более важно, алгоритм не имеет особого смысла. На мой взгляд, это, скорее всего, означает, что код не делает то, что вы намереваетесь делать. Если вы не объясните, чего вы на самом деле пытаетесь достичь , мы не можем понять, в чем заключается настоящая проблема и как ее решить.


Я все еще не совсем понимаю, чего вы пытаетесь достичь, но я думаю, что решение будет включать одно или оба из следующих действий:

  • Измените класс реализации myList на один из классов одновременных коллекций, который делает допускающим одновременное изменение; например ConcurrentLinkedDeque.

  • Заменить внешний цикл следующим:

    while (!myList.isEmpty()) {
        Object obj = myList.remove(0);
        ...
    }
    

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

В любом случае вам нужно беспокоиться о том, как завершить цикл, если он не продвигается в обработке записей.

Сложность "большого О" также вызывает озабоченность, но ее невозможно охарактеризовать, не понимая, что делает "другое условие".

1 голос
/ 06 ноября 2011

Полагаю, вы получаете исключение ConcurrentModificationException.

Вы не можете изменять список в итераторе, пока второй повторяет его.

http://download.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...