Динамическое удаление элементов из списка - PullRequest
5 голосов
/ 19 ноября 2011

У меня проблема с удалением элементов списка во время перебора списка.Код:

For (WebElement element: list){
    if (!element.isEnabled() || !element.isSelected()){
        list.remove(element);
    }
}

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

Мой вопрос: как еще мне удалить элементы, которые не являются enabled или selected из этого списка?

Ответы [ 4 ]

8 голосов
/ 19 ноября 2011

Изменение списка во время итерации по нему, выход за пределы использования итератора, приводит к неопределенному поведению.Вам придется использовать итератор явно:

Iterator<WebElement> iter = list.iterator();
while (iter.hasNext()) {
    WebElement element = iter.next();
    if (!element.isEnabled() || !element.isSelected()) {
        iter.remove();
    }
}

Подробнее см. *.

8 голосов
/ 19 ноября 2011

Самый простой способ удалить элементы из списка в цикле - это использовать ListIterator и удалять элементы с помощью процедуры iterator.remove()

3 голосов
/ 19 ноября 2011

Другие предложили использовать итератор списка. Это оказалось полезным для меня, но, к сожалению, оно основано на методе remove(), который интерфейс Iterable<E> считает необязательным.

Квот Javadoc, никогда (акцент мой):

void remove ()

Удаляет из базовой коллекции последний элемент, возвращаемый итератор (необязательная операция) .

Чтобы обойти то, что оказалось более полезным для меня, это список удаления.

List<E> removed = new ArrayList<E>();
for(E element : list) {
    if(someCondition) removed.add(element);
}
list.removeAll(removed);

Это дает дополнительное преимущество, так как дает вам историю того, что вы удалили, так же, как это делает метод удаления.

0 голосов
/ 19 ноября 2011

ConcurrentModificationException является результатом того факта, что синтаксис for-each является просто синтаксическим сахаром для использования интерфейса Iterator.

Итераторы списка имеют так называемый атрибут fail-fast, означающий, чтолюбое изменение, внесенное в список, кроме интерфейса, предоставленного итератором, немедленно делает его недействительным.Попытка использовать недействительный итератор вызывает ваше исключение.

@ Claudiu уже опубликовал этот код, но для ясности я также выложу его здесь.Чтобы сделать то, что вы пытаетесь сделать, вам придется отказаться от причудливого синтаксиса и использовать чистый итератор.

Iterator<WebElement iter = list.iterator();
while (iter.hasNext()) {
    WebElement element = iter.next();
    if (!element.isEnabled() || !element.isSelected()) {
        iter.remove();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...