Улучшен цикл (или «для каждого»), повторяющий элемент, который он только что удалил - выдает ошибку - PullRequest
1 голос
/ 09 ноября 2010

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

Я создал список, в котором есть только теги xml.Цель алгоритма состоит в том, чтобы перебрать список элементов и удалить элемент, если выполняется условие (в данном случае, если оно начинается с определенной строки).См. Ниже:

for (Element appinfo : appinfos) {

                    if (appinfo.getText().startsWith(
                            PARAMETER_DESCRIPTION_APPINFO)) {
                         removeAppInfoElement(appinfo, name, appinfo.getText());
                    }
}

Однако цикл, похоже, пытается выполнить итерацию для только что удаленного элемента.Кто-нибудь видит что-то не так с этим?Нужно ли отказываться от улучшенного цикла for или копать глубже из-за причины проблемы?

Ответы [ 4 ]

3 голосов
/ 09 ноября 2010

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

1 голос
/ 09 ноября 2010

ответ willcodejavaforfood - один из способов сделать это.

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

final Iterator<Element> iter = appinfos.iterator();
while (iter.hasNext()) {
    if (iter.next().getText().startsWith(
        PARAMETER_DESCRIPTION_APPINFO)) {
        iter.remove();
    }
}

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

Во всех случаях изменение коллекции во время ее итерации обычно приводит к возникновению плохих вещей.

1 голос
/ 09 ноября 2010

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

Вместо расширенного цикла for используйте Iterator и вызовите функцию remove(), например:

for (Iterator it = appinfos.iterator(); it.hasNext();) {
    Element appinfo : it.next();
    if (someCondition) {
        it.remove();
    }
}
1 голос
/ 09 ноября 2010

Да, это не сработает.

Добавьте все элементы, которые вы хотите удалить, в новую коллекцию, а затем выполните removeAll с этими элементами в исходной коллекции.

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