2011-11-18 179 views
5

我在遍歷列表時刪除列表元素時遇到問題。代碼:動態刪除列表中的元素

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

我得到ConcurrentModificationException,我完全理解。我在通過列表的循環中刪除列表中的項目。直觀地說,這會搞砸循環的索引。

我的問題是,我該如何從該列表中刪除不是enabledselected的元素?

回答

8

以除去從一個列表中的元素在一個循環中最簡單的方法是使用常規iterator.remove()

+0

我不知道它是否一定是最簡單的。 'remove()'是'Iterator '接口上的一個可選功能。值得注意的是'remove()'在'Iterator '上,並且僅僅由'ListIterator '繼承。 – corsiKa

6

修改列表,同時通過它使用迭代的外迭代,在某種程度上,結果,以使用一個ListIterator和刪除元素在未定義的行爲。您必須明確使用迭代器:

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

有關更多信息,請參閱this question

+0

嗯,我明白了。因此,如果我想將'Iterator'轉換回'List',有沒有比在循環中逐個添加每個元素更簡單的方法? – jamesfzhang

+2

這不會將'List'轉換爲'Iterator' - 一個'Iterator'只是一個作用於該列表本身的對象 - 它是一個迭代整個列表的接口。當你調用'iter.remove()'時,它確實在修改底層列表。 – Claudiu

+0

哇,太棒了!謝謝。 – jamesfzhang

0

從以下事實的ConcurrentModificationException結果可知,對於-每個語法只是使用Iterator接口語法糖。

列表迭代器有什麼是被稱爲「快速失敗」的屬性,這意味着任何改變從迭代器提供的接口列表發不談,立即失效說迭代器。試圖使用失效的迭代器觸發你的異常。

@Claudiu已經張貼了這個代碼,但爲了清楚起見,我就會把它在這裏。爲了做你想做的事情,你將不得不放棄花哨的語法,並使用一個簡單的迭代器。

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

其他人建議使用列表迭代器。這對我來說已經證明是有用的,但不幸的是它依賴於一種方法remove(),這被Iterable<E>接口認爲是可選的。

答曰的Javadoc,永不復還(重點煤礦):

無效刪除()

從底層集合的最後一個元素通過 迭代器(可選操作)返回刪除。

要解決這個問題已被證明對我來說更有用的是刪除列表。

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

這還有一個額外的好處,就是您可以像刪除方法一樣爲您提供刪除內容的歷史記錄。

+0

我非常喜歡這個(+1)。然而,元素E應該有一個適當的覆蓋等於方法 – GETah

+1

@GETah不一定。沒有它就可以正常工作,甚至可能是首選。你可能會讓他們來自一種工廠方法,在這種方法中,你對equals方法的需求少得多,嚴格依賴於平等的參考。 – corsiKa

+1

哇,我也很喜歡這個!非常好的想法。 – jamesfzhang