简体   繁体   中英

Dynamically removing elements from List

I am having an issue removing elements of a list while iterating through the list. Code:

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

I get a ConcurrentModificationException , which I totally understand. I am removing an item from a list while in the loop that goes through the list. Intuitively, that would screw up the indexing of the loop.

My question is, how else should I remove elements that are either not enabled or selected from this list?

从循环列表中删除元素的最简单方法是使用ListIterator并使用例程iterator.remove()删除元素

Modifying a list while iterating through it, in a way outside of using the iterator, results in undefined behavior. You'll have to use an iterator explicitly:

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

See this question for more.

Others have suggested using the list iterator. That has proven useful to me, but unfortunately it relies on a method, remove() , which is considered optional by the Iterable<E> interface.

Quoth the Javadoc, nevermore (emphasis mine):

void remove()

Removes from the underlying collection the last element returned by the iterator (optional operation) .

To get around that has proven more useful to me is a removal list.

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

This has the added benefit of giving you a history of what you removed, just like the remove method does.

The ConcurrentModificationException results from the fact that the for-each syntax is just syntactic sugar for using the Iterator interface.

List iterators have what is known as the "fail-fast" attribute, meaning that any change made to the list aside from the interface provided by the iterator, immediately invalidates said iterator. Trying to use an invalidated iterator triggers your exception.

@Claudiu has already posted this code, but for clarity, I will put it here as well. In order to do what you're trying to do, you'll have to drop the fancy syntax and use a bare Iterator.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM