Apa perbedaan antara ArrayList.clear () dan ArrayList.removeAll ()?

283

Dengan asumsi yang arraylistdidefinisikan sebagai ArrayList<String> arraylist, arraylist.removeAll(arraylist)setara dengan arraylist.clear()?

Jika demikian, dapatkah saya berasumsi bahwa clear()metode ini lebih efisien untuk mengosongkan daftar array?

Apakah ada peringatan dalam menggunakan arraylist.removeAll(arraylist)bukan arraylist.clear()?

ateiob
sumber
Kemungkinan akibat wajar dari pertanyaan ini: Kapan satu dapat digunakan dan bukan yang lain?
Corey Ogburn
3
@Corey: kapan mungkin setiap orang ingin menggunakan arraylist.removeAll(arraylist)? Saya sama sekali tidak melihat alasan untuk melakukan itu.
Joachim Sauer
@ Joachim Sauer Itulah yang ingin saya verifikasi. Terima kasih +2. Tetapi apakah perbedaan antara elementData[i] = nulldan e.remove()signifikan?
ateiob
Tidak ada alasan waras untuk melakukan arrList.removeAll(arrList)bukan arrList.clear(). arrList1.removeAll(arrList2)adalah masalah yang berbeda.
Vlad
3
Jika saja implementasi removeAll () dimulai dengan baris ini, maka seluruh diskusi ini bisa jadi jauh lebih menghibur !!! if (c == this && !isEmpty()) { clear(); return true; }. Saya harus mengirimkan ini ke OpenJDK sebagai tambalan! ;-)
Julius Musseau

Jawaban:

396

Kode sumber untuk clear():

public void clear() {
    modCount++;

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

    size = 0;
}

Kode sumber untuk removeAll()(Sebagaimana didefinisikan dalam 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() jauh lebih cepat karena tidak harus berurusan dengan semua pemanggilan metode tambahan.

Dan seperti yang ditunjukkan Atrey, c.contains(..)meningkatkan kompleksitas waktu removeAllke O (n 2 ) sebagai lawan cleardari O (n).

Jeffrey
sumber
29
Catatan yang c.contains(...)mengkuadratkan kompleksitas waktu operasi akan membuat jawaban ini lengkap.
Atreys
8
Sumber yang kuat dalam hal ini. (Untuk semua jawaban lain: Gunakan sumbernya, Luke.) Perhatikan betapa jelasnya () dapat diimplementasikan sebagai hanya satu baris, size = 0; tetapi pengumpulan sampah tidak akan tahu untuk mengumpulkan elemen-elemen di bagian array yang tidak terjangkau.
Julius Musseau
2
e.remove () jauh lebih kompleks! e.remove () juga kuadratkan kompleksitasnya, seperti halnya c.contains (...). Pada ArrayList, e.remove () memanggil ArrayList.remove (int index), yang harus menggeser sisa array menjadi satu.
Julius Musseau
1
@ateiob e.remove () adalah dua pemanggilan metode tambahan, pengecekan jangkauan, dan pengembalian objek (internal ke AbstractList.Itr.remove()dan ArrayList.remove(int)), juga
Atreys
2
@ julius Jika berhasil, size = 0; elementData = new Object[10];semua sisanya akan menjadi sampah yang dikumpulkan, karena array backing tidak memiliki referensi luar.
corsiKa
51

Kompleksitas waktu ArrayList.clear()is O(n)dan of removeAllis O(n^2).

Jadi ya, ArrayList.clearjauh lebih cepat.

Geoff
sumber
15

The clear()Metode menghapus semua elemen tunggal ArrayList. Ini operasi cepat, karena hanya mengatur elemen array null.

The removeAll(Collection)metode, yang merupakan warisan dari AbstractCollection, menghapus semua elemen yang ada di koleksi argumen dari koleksi Anda memanggil metode pada. Ini operasi yang relatif lambat, karena harus mencari melalui salah satu koleksi yang terlibat.

Ernest Friedman-Hill
sumber
Saya pikir itu hanya mengatur semua, bukan beberapa elemen menjadi nol. Jika bukan itu masalahnya, bagaimana ia memutuskan elemen mana yang harus disetel ke nol?
Farid
2
@Farid maaf, bahasa Inggris saya terlalu informal di sini. Saya memang bermaksud bahwa itu mengatur semua elemen menjadi nol. Saya akan memperbaikinya!
Ernest Friedman-Hill
7

Kecuali ada optimasi khusus yang memeriksa apakah argumen yang diteruskan removeAll()adalah koleksi itu sendiri (dan saya sangat ragu bahwa optimasi seperti itu ada di sana) itu akan secara signifikan lebih lambat daripada yang sederhana .clear().

Terlepas dari itu (dan setidaknya sama pentingnya): arraylist.removeAll(arraylist)hanya membingungkan, kode membingungkan. Ini adalah cara yang sangat terbelakang untuk mengatakan "hapus koleksi ini". Keuntungan apa yang dimilikinya dibanding yang sangat dimengerti arraylist.clear() ?

Joachim Sauer
sumber
7

Mereka melayani tujuan yang berbeda. clear()membersihkan instance kelas, removeAll()menghapus semua objek yang diberikan dan mengembalikan status operasi.

lucapette
sumber
dapatkah Anda menyediakan sumber daya untuk membaca materi di atas untuk referensi lebih lanjut
Kasun Siyambalapitiya
1
@KasunSiyambalapitiya Bagaimana dengan jawaban yang diterima , yang berisi kode sumber untuk keduanya?
Abdul
5

clear() akan melalui Array yang mendasarinya dan mengatur setiap entri menjadi nol;

removeAll(collection)akan melalui ArrayList memeriksa koleksi dan remove(Object)jika ada.

Saya akan membayangkan itu clear()jauh lebih cepat daripada menghapus semua karena itu tidak membandingkan, dll.

Nicholas
sumber
2

Hapus lebih cepat karena tidak mengulang elemen untuk dihapus. Metode ini dapat mengasumsikan bahwa SEMUA elemen dapat dihapus.

Remove alltidak berarti menghapus semua elemen dalam daftar, hanya yang disediakan sebagai parameter HARUS dihapus. Oleh karena itu, lebih banyak upaya diperlukan untuk menjaga yang tidak boleh dihapus.

KLARIFIKASI

Dengan 'loop', maksud saya itu tidak harus memeriksa apakah elemen tersebut harus disimpan atau tidak. Itu dapat mengatur referensi nulltanpa mencari melalui daftar elemen yang disediakan untuk dihapus.

ClearIS lebih cepat dari deleteall.

Jérôme Verstrynge
sumber
1
Aku cukup yakin bahwa ArrayList.clear()memiliki loop juga.
Joachim Sauer
@JVerstry Maksud Anda clear () tidak menghapus elemen yang dihapusnya dari ArrayList?
ateiob
1
Salah, hapus lakukan perulangan di larik internal dan set semua referensi ke nol untuk memungkinkan pengumpul sampah melakukan tugasnya.
devconsole
1
@ Joachim, @devconsole: Saya pikir maksudnya tidak perlu mengulang / mengulang daftar yang diberikan sebagai parameter. target.removeAll(param)akan beralih lagi paramdan kemudian panggilan target.contains(...)yang beralih berakhir target.
Vlad
2
-3 Agak keras. Jika JVerstry mau, dia bisa menulis implementasi Java sendiri dari awal yang tidak diulang. clear () dapat diimplementasikan di O (1), tanpa loop, sedangkan removeAll () HARUS memiliki beberapa jenis algoritma O (n), tidak ada cara untuk memenuhi kontrak removeAll () API tanpa memeriksa semua elemen.
Julius Musseau
1

clear () akan jauh lebih efisien. Itu hanya akan menghapus setiap item. Menggunakan removeAll (arraylist) akan membutuhkan lebih banyak pekerjaan karena akan memeriksa setiap item dalam arraylist untuk melihat apakah ada dalam arraylist sebelum menghapusnya.

CDelaney
sumber
-8

Array => setelah ruang dialokasikan untuk variabel Array pada waktu berjalan, ruang yang dialokasikan tidak dapat diperpanjang atau dihapus.

ArrayList => Ini bukan kasus di arraylist. ArrayList dapat tumbuh dan menyusut pada saat dijalankan. Ruang yang dialokasikan dapat diminimalkan atau dimaksimalkan pada saat dijalankan.

Arun Kumar
sumber
Ini tidak menjawab pertanyaan yang merupakan perbedaan antara ArrayList.clear () dan ArrayList.removeAll (), bukan perbedaan antara Array dan ArrayList.
Pierre
Jawaban ini tidak perlu. Bukan itu pertanyaannya.
Serafim Costa