2011-06-08 21 views
5

ArrayListをフィルタリングし、見つかった要素を削除する必要があります。 Javaには比較的新しいので、これを達成するための最も効率的な方法(モバイルデバイス上で実行されるため問題)が何であるか疑問に思っています。現在、私はこれをしています:Java:効率的なArrayListフィルタリング?

// We display only top-level dealers (parentId=-10) 
ArrayList<DealerProductCount> subDealers = new ArrayList<DealerProductCount>(); 
for (DealerProductCount dealer : wsResponse.Dealers) { 
    if (dealer.ParentId != -10) subDealers.add(dealer); 
} 
wsResponse.Dealers.removeAll(subDealers); 

一時的なオブジェクトなしで行うことはできますか?おそらく、反復されるリストの要素を直接操作(削除)することによって?

+1

他のデータ構造では、アイテムの削除が効率的です。 LinkedListからの削除はO(n)のパフォーマンスを持ちます。 HashMapからの削除は、一定の時間パフォーマンスを持ちます。 –

答えて

16

は、いくつかの考えを必要とします。

Iterator<DealerProductCount> it = wsResponse.Dealers.iterator(); 
while (it.hasNext()) { 
    if (it.next().ParentId != -10) { 
     it.remove(); 
    } 
} 

問題は、各時間はあなたが(平均的に)コピーの要素を削除することで、残りの要素の半分:素朴なアプローチは、このようなものです。これは、ArrayListから要素を削除するには、要素を1つ削除した後にすべての要素を左にコピーする必要があるからです。

削除する要素のリストを含むオリジナルのソリューションは、基本的に同じことを行います。残念ながら、ArrayListのプロパティはremoveAllが上記よりもうまく行かないようにします。

あなたは要素の数を削除することが予想される場合は、以下がより効率的です。

ArrayList<DealerProductCount> retain = 
     new ArrayList<DealerProductCount>(wsResponse.Dealers.size()); 
for (DealerProductCount dealer : wsResponse.Dealers) { 
    if (dealer.ParentId == -10) { 
     retain.add(dealer); 
    } 
} 
// either assign 'retain' to 'wsResponse.Dealers' or ... 
wsResponse.Dealers.clear(); 
wsResponse.Dealers.addAll(retain); 

私たちは二度(ほぼ)全リストをコピーしているので、あなたが削除した場合、これは(平均で)さえ壊れなければなりませんわずか4要素です。


典型的な関数型プログラミング言語/ライブラリは、フィルタメソッドをサポートしており、リストを1回通過するだけでこのタスクを実行できます。すなわちより多く効率的になる。私は、Javaがlambdaをサポートしている場合、そしてそれらを使用するためにコレクションAPIが強化されている場合、大幅な改善が期待できると思います。

+0

Stephenに感謝します。したがって、Take-homeメッセージは、既存の要素から要素を削除するよりも、新しいArrayListを満たす方が一般的に優れています。知っておいてよかった! – Bachi

7

イテレータを使用する場合は、反復中に安全に要素を削除できます。

+1

(iteratorがremoveの実装を提供する場合、 'UnsupportedOperationException'がスローされる可能性がありますので、これはあなたのIteratorをよく知っていれば動作します) –

4

一つの方法は、代わりにそれぞれのための反復子を使用します効率的ArrayListからの要素の数を除去

Iterator<DealerProductCount> iter = wsResponse.Dealers.iterator() 
while(iter.hasNext()) { 
    if (iter.next().ParentId != -10) iter.remove(); 
} 
関連する問題