簡體   English   中英

Java如何有效地從列表中刪除元素

[英]Java how to remove element from List efficiently

好的,這是我腦海中困擾了幾天的概念驗證:

假設我有:

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--;
}

它應該以這種方式工作(至少在我的腦海中如此),但是將迭代器搞混並不是真正的好習慣。

我認為以其他方式可以創建“刪除列表”,然后向列表中添加需要從列表a中刪除的項目,但這只會浪費資源。

那么,有效地從列表中刪除項目的最佳實踐是什么?

請改用Iterator並使用Iterator#remove方法:

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

根據您的問題:

與迭代器打交道不是一個好習慣

實際上,如果您面向接口編碼並直接使用List而不是ArrayList ,則使用get方法可能會瀏覽所有集合以獲取所需的元素(例如,如果您的List由單個鏈接列表支持)。 因此,這里的最佳實踐是使用迭代器而不是使用get

有效地從列表中刪除項目的最佳實踐是什么?

不僅對於List ,而且對於任何支持Iterable Collection ,並且假設您沒有直接訪問元素的索引或某種鍵(例如Map ),刪除元素的最佳方法是使用Iterator#remove

您有三個主要選擇:

  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循環,並且僅在刪除項目的情況下才遞增index變量。

     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; } } 

請記住,除非您知道要處理ArrayList ,否則List#get(int)的開銷可能會很高(可能是遍歷)。 但是,如果您知道自己正在處理ArrayList (或類似的東西),那么...

您的第一個示例可能會導致一次性錯誤,因為一旦刪除對象,列表的索引就會更改。 如果您想快速了解它,請使用iterator或List自己的.remove()函數:

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

要么:

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

ArrayList.retainAll具有一個“智能”實現,可以將時間做為線性時間。 您可以只使用list.retainAll(Arrays.asList("foo", "bar"))然后在那一行中獲得快速的實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM