2014-04-07 94 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")),您将在该行中获得快速实施。