Reputation: 4473
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?
Upvotes: 6
Views: 6808
Reputation: 82579
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.
Upvotes: 3
Reputation: 3155
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();
}
}
Upvotes: 0
Reputation: 229361
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.
Upvotes: 8
Reputation: 49187
The easiest way to remove elements from a list in a loop is to use an ListIterator
and remove elements using the routine iterator.remove()
Upvotes: 8