[英]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
。
您有三個主要選擇:
使用Iterator
,因為它具有方便的remove
方法。 :-)
Iterator<String> it = list.iterator(); while (it.hasNext()) { if (/*...you want to remove `it.next()`...*/) { it.remove(); } }
在列表中向后循環,因此,如果刪除某些內容,則對於下一次迭代無關緊要。 這也具有只調用一次 list.size()
的優點。
for (int index = list.size() - 1; index >= 0; --index) { // ...check and optionally remove here... }
請改為使用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.