我在迭代列表时删除列表元素时遇到问题。代码:
For (WebElement element: list){
if (!element.isEnabled() || !element.isSelected()){
list.remove(element);
}
}
我得到ConcurrentModificationException
,我完全理解。我在循环列表中删除列表中的项目。直观地说,这会搞砸循环的索引。
我的问题是,我该如何从此列表中删除不是enabled
或selected
的元素?
答案 0 :(得分:8)
从循环列表中删除元素的最简单方法是使用ListIterator
并使用例程iterator.remove()
删除元素
答案 1 :(得分:8)
在迭代使用迭代器之外修改列表会导致未定义的行为。您必须明确使用迭代器:
Iterator<WebElement> iter = list.iterator();
while (iter.hasNext()) {
WebElement element = iter.next();
if (!element.isEnabled() || !element.isSelected()) {
iter.remove();
}
}
有关详情,请参阅this question。
答案 2 :(得分:3)
其他人建议使用list迭代器。这对我来说已经证明是有用的,但遗憾的是它依赖于remove()
方法,Iterable<E>
接口认为它是可选的。
Javadoc,永远不要(强调我的):
void remove()
从底层集合中删除返回的最后一个元素 迭代器(可选操作)。
为了解决这个问题,对我来说更有用的是删除列表。
List<E> removed = new ArrayList<E>();
for(E element : list) {
if(someCondition) removed.add(element);
}
list.removeAll(removed);
这样做的另一个好处是可以为您提供删除内容的历史记录,就像删除方法一样。
答案 3 :(得分:0)
ConcurrentModificationException
导致for-each语法只是使用Iterator接口的语法糖。
列表迭代器具有所谓的“fail-fast”属性,这意味着除了迭代器提供的接口之外对列表所做的任何更改都会立即使所述迭代器无效。尝试使用无效的迭代器会触发您的异常。
@Claudiu已经发布了这段代码,但为了清楚起见,我也会把它放在这里。为了做你想做的事情,你必须删除花哨的语法并使用一个裸Iterator。
Iterator<WebElement iter = list.iterator();
while (iter.hasNext()) {
WebElement element = iter.next();
if (!element.isEnabled() || !element.isSelected()) {
iter.remove();
}
}