2014-04-07 54 views
1

好吧,這是一個驗證的概念,我有我的頭一直纏着我了好幾天:的Java如何從列表中刪除元素有效

比方說,我有:

List<String> a = new ArrayList<String>(); 
a.add("foo"); 
a.add("buzz"); 
a.add("bazz"); 
a.add("bar"); 

for (int i = 0; i < a.size(); i++) 
{ 
    String str = a.get(i); 
    if (!str.equals("foo") || !str.equals("bar")) a.remove(str); 
} 

這將以列表[「foo」,「bazz」,「bar」]結尾,因爲它會讀取索引1處的字符串(「buzz」),將其刪除,索引2處的字符串(「bazz」)會跳轉到索引1,它會被繞過而不被驗證。

我想出了:

List<String> a = new ArrayList<String>(); 
a.add("foo"); 
a.add("buzz"); 
a.add("bazz"); 
a.add("bar"); 

for (int i = 0; i < a.size(); i++) 
{ 
    String str = a.get(i); 
    boolean removed = false; 
    if (!str.equals("foo") || !str.equals("bar")) 
    { 
     a.remove(str); 
     removed = true; 
    } 
    if (removed) i--; 
} 

應該以這種方式工作(ATLEAST它在我的頭笑),但對於搞亂迭代器是不是真的很好的做法。

我想其他的辦法是建立一個「刪除列表」和添加項目到列表中需要從列表中刪除,但是這將是隻是普通的資源浪費。

那麼,有效地從列表中刪除項目的最佳做法是什麼?

+4

你應該使用Iterator。 –

+1

爲什麼不使用'Set'? – fge

+0

可能是http://stackoverflow.com/questions/2043783/how-to-efficiently-performance-remove-many-items-from-list-in-java?rq=1 – Khaelid

回答

2

你有三種主要的選擇:

  1. 使用一個Iterator ,因爲它有方便的remove方法。 :-)

    Iterator<String> it = list.iterator(); 
    while (it.hasNext()) { 
        if (/*...you want to remove `it.next()`...*/) { 
         it.remove(); 
        } 
    } 
    
  2. 落後通過列表,因此,如果你刪除的東西,這不要緊,下一次迭代。這也具有僅僅呼叫list.size()一次的優點。

    for (int index = list.size() - 1; index >= 0; --index) { 
        // ...check and optionally remove here... 
    } 
    
  3. 使用while環代替,只有增加索引變量,如果你刪除該項目。

    int index = 0; 
    while (index < list.size()) { 
        if (/*...you want to remove the item...*/) { 
         list.removeAt(index); 
        } else { 
         // Not removing, move to the next 
         ++index; 
        } 
    } 
    

記住,除非你知道你處理的ArrayListList#get(int)成本可能很高(這可能是一個遍歷)。但是,如果你知道正在與ArrayList(或類似)的交易,然後...

3

使用Iterator來代替,而Iterator#remove方法:

for (Iterator<String> it = a.iterator(); it.hasNext();) { 
    String str = it.next(); 
    if (!str.equals("foo") || !str.equals("bar")) { 
     it.remove(); 
    } 
} 

從你的問題:

搞亂了迭代器是不是真的好做法

事實上,如果你code oriented to interfaces並使用List,而不是直接ArrayList使用get方法可能成爲進入通過所有的集合導航,以獲得所需的元素(例如,如果你有一個單鏈表支持的List)。因此,這裏的最佳做法是使用迭代器而不是使用get

什麼是從有效列表中移除項目的最佳實踐?

不僅爲List S,但爲支持Iterable,假設你沒有索引或某種關鍵的(如在一個Map)直接訪問對元件的任何Collection,最好的辦法刪除元素將使用Iterator#remove

+0

謝謝,但在這種情況下,使用while循環不應該更容易嗎? like: Iterator it = a.iterator(); (it.hasNext()) { String str = it.next(); // code } – DarkW

+1

@DarkW你可以使用'for'或者'while'來遍歷Iterator的元素。使用你感覺更舒適的方法。 –

+1

@DarkW檢查這裏:http://www.javapractices.com/topic/TopicAction.do?Id=125 –

1

你的第一個例子可能會導致關閉的情況的一個錯誤,因爲一旦你刪除一個對象列表的索引會發生變化。如果你想快了,使用iterator或列表自身.remove()功能:

Iterator<String> itr = yourList.iterator(); 
while (itr.hasNext()) { 
    if ("foo".equals(itr.next()) { 
     itr.remove(); 
    } 
} 

或者:

yourList.remove("foo"); 
yourList.removeAll("foo"); // removes all 
1

ArrayList.retainAll具有「智能」的實現,做正確的事是線性的時間。您可以使用list.retainAll(Arrays.asList("foo", "bar")),您將在該行中獲得快速實施。