ArrayList.clear()とArrayList.removeAll()の違いは何ですか?


283

arraylistとして定義されていると仮定するとArrayList<String> arraylist、とarraylist.removeAll(arraylist)同等arraylist.clear()です。

もしそうなら、私はclear()メソッドが配列リストを空にするためにより効率的であると仮定できますか?

arraylist.removeAll(arraylist)代わりに使用する際の注意点はありarraylist.clear()ますか?


この質問の可能な帰結:いつ一方が他方の代わりに使用される可能性がありますか?
Corey Ogburn 2011

3
@Corey:誰もがいつ使用したいのarraylist.removeAll(arraylist)でしょうか?そんなことをする理由は全くないと思います。
Joachim Sauer

@Joachim Sauerそれはまさに私が確認したかったことです。おかげで+ 2。しかし、間の差であるelementData[i] = nulle.remove()重要なものは?
ateiob 2011

arrList.removeAll(arrList)代わりに行う理由はありませんarrList.clear()arrList1.removeAll(arrList2)別の問題です。
Vlad

3
removeAll()の実装のみがこの行で始まった場合、この全体の議論は、はるかに楽しいものになる可能性があります!!! if (c == this && !isEmpty()) { clear(); return true; }。これをパッチとしてOpenJDKに提出する必要があります!;-)
Julius Musseau、2011

回答:


396

のソースコードclear()

public void clear() {
    modCount++;

    // Let gc do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

removeAll()(で定義されているAbstractCollection)のソースコード:

public boolean removeAll(Collection<?> c) {
    boolean modified = false;
    Iterator<?> e = iterator();
    while (e.hasNext()) {
        if (c.contains(e.next())) {
            e.remove();
            modified = true;
        }
    }
    return modified;
}

clear() これらの余分なメソッド呼び出しをすべて処理する必要がないため、はるかに高速です。

また、Atreyが指摘するように、のO(n )ではなく、O(n 2c.contains(..)の時間の複雑さが増加します。removeAllclear


29
c.contains(...)操作の時間の複雑さを2乗すると、この答えは完全になります。
Atreys、2011

8
これはソースが強いです。(他のすべての答えへ:ソース、Lukeを使用してください。)clear()が1行のsize = 0として実装されていることに注意してください。しかし、ガベージコレクションは、配列の到達不能な部分の要素を収集することを知りません。
Julius Musseau、2011

2
e.remove()はもっと複雑です!e.remove()も、c.contains(...)と同様に、複雑さを2乗します。ArrayListでは、e.remove()はArrayList.remove(int index)を呼び出します。これは、配列の残りの部分を1つ上にシフトする必要があります。
Julius Musseau、2011

1
@ateiob e.remove()は、2つの追加のメソッド呼び出し、範囲チェック、およびオブジェクトの戻り(内部AbstractList.Itr.remove()およびArrayList.remove(int))でもあります
Atreys

2
@juliusこれを行うとsize = 0; elementData = new Object[10];、バッキング配列には外部参照がないため、残りはすべてガベージコレクションされます。
corsiKa 2011

51

時間の複雑さはArrayList.clear()あるO(n)とのremoveAllIS O(n^2)

だからはい、ArrayList.clearはるかに高速です。


15

このclear()メソッドは、単一ののすべての要素を削除しますArrayList。配列要素をに設定するだけなので、高速な操作nullです。

removeAll(Collection)継承されたメソッドは、AbstractCollectionあなたが上のメソッドを呼び出して、コレクションから引数コレクション内にあるすべての要素を削除します。関連するコレクションの1つを検索する必要があるため、操作は比較的低速です。


すべてを設定するだけで、一部の要素をnullに設定しないと思いました。そうでない場合、どの要素をnullに設定するかをどのように決定しましたか?
ファリッド

2
@Farid申し訳ありませんが、私の英語はここではあまりにも非公式です。実際、すべての要素をnullに設定することを意味していました。直します!
Ernest Friedman-Hill

7

渡された引数がremoveAll()コレクション自体であるかどうかをチェックする特定の最適化がない限り(そして、そのような最適化がそこにあることを私は非常に疑っています)、単純なものより大幅に遅くなります.clear()

それとは別に(そして少なくとも同等に重要です):arraylist.removeAll(arraylist)単にあいまいで混乱を招くコードです。「このコレクションをクリアしてください」という非常に逆の言い方です。それは非常に理解しやすい ものよりどのような利点がありarraylist.clear()ますか?


7

彼らは異なる目的を果たします。clear()クラスのインスタンスをクリアremoveAll()し、指定されたすべてのオブジェクトを削除して、操作の状態を返します。


さらに参照できるように、上記の問題について読むためのリソースを提供してもらえますか
Kasun Siyambalapitiya

1
@KasunSiyambalapitiya 2つのソースコードを含む、受け入れられた回答はどうですか?
Abdul

5

clear() 基になる配列を調べ、各エントリをnullに設定します。

removeAll(collection)コレクションとremove(Object)それが存在する場合はそれをチェックするためにArrayListを通過します。

clear()比較しているわけではないので、removeAllよりもはるかに高速だと思います。


2

削除する要素をループしないため、クリアの方が高速です。この方法では、すべての要素を削除できると想定できます。

Remove all必ずしもリスト内のすべての要素を削除することを意味するのではなく、パラメータとして提供された要素のみを削除する必要があります。したがって、削除すべきでないものを保持するために、より多くの努力が必要です。

明確化

「ループ」とは、要素を保持する必要があるかどうかを確認する必要がないことを意味します。null提供されている削除する要素のリストを検索せずに、参照をに設定できます。

Clearより速いですdeleteall


1
それArrayList.clear()もループする必要があると確信しています。
ヨアヒムザウアー

@JVerstry clear() ArrayListから削除した要素を削除しないということですか?
ateiob 2011

1
間違って、clearは内部配列をループし、ガベージコレクターがその処理を実行できるようにすべての参照をnullに設定します。
devconsole 2011

1
@ Joachim、@ devconsole:パラメータとして指定されたリストをループまたは反復する必要がないことを意味していると思います。target.removeAll(param)反復しparam、次にtarget.contains(...)反復するwhich を呼び出しますtarget
Vlad

2
-3は少し厳しいです。JVerstryが望めば、ループしない独自のJava実装をゼロから作成できます。clear()ループなしでO(1)に実装できますが、removeAll()は何らかのO(n)アルゴリズムを持つ必要があります。すべての要素を調べずにremoveAll()APIの規約を満たす方法はありません。
Julius Musseau、2011

1

clear()の方がはるかに効率的です。それは単にすべてのアイテムを削除します。removeAll(arraylist)を使用すると、削除する前にarraylist内のすべての項目をチェックして、それがarraylistに存在するかどうかを確認するため、さらに多くの作業が必要になります。


-8

Array =>実行時に配列変数にスペースが割り当てられると、割り当てられたスペースを拡張または削除することはできません。

ArrayList =>これはarraylistには当てはまりません。ArrayListは実行時に拡大および縮小できます。割り当てられたスペースは、実行時に最小化または最大化できます。


これは、ArrayList.clear()とArrayList.removeAll()の違いである質問には答えません。ArrayとArrayListの違いではありません。
ピエール14

この答えは不要です。それが問題ではありません。
セラフィムコスタ2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.