remove () pada Daftar yang dibuat oleh Arrays.asList () melontarkan UnsupportedOperationException


91

Saya memiliki koleksi c1<MyClass>dan array a<MyClass>. Saya mencoba untuk mengubah array menjadi koleksi c2dan lakukan c1.removeAll(c2), Tapi ini melempar UnsupportedOperationException. Saya menemukan bahwa asList()kelas Array mengembalikan Arrays.ArrayListkelas dan kelas ini mewarisi removeAll()dari AbstractList()yang pelaksanaannya melempar UnsupportedOperationException.

    Myclass la[] = getMyClass();
    Collection c = Arrays.asList(la);
    c.removeAll(thisAllreadyExistingMyClass);

Apakah ada cara untuk menghilangkan elemen? tolong bantu


Jawaban:


173

Arrays.asListmengembalikan Listpembungkus di sekitar larik. Pembungkus ini memiliki ukuran tetap dan secara langsung didukung oleh larik, dan dengan demikian panggilan ke setakan mengubah larik, dan metode lain apa pun yang mengubah daftar akan melontarkan UnsupportedOperationException.

Untuk memperbaikinya, Anda harus membuat daftar baru yang dapat diubah dengan menyalin konten daftar pembungkus. Ini mudah dilakukan dengan menggunakan ArrayListkonstruktor yang membutuhkan Collection:

Collection c = new ArrayList(Arrays.asList(la));

1
Saya melihat kode sumber untuk java.util.Arrays asList()metode, dan tampaknya mengembalikan file ArrayList. Namun, ketika saya melakukan System.out.println(list.getClass());, saya mengerti class java.util.Arrays$ArrayList. Jadi itu menggunakan ArrayListkelas dalam , yang tidak memiliki metode addatau remove. Saya hanya bertanya-tanya apa gunanya memiliki ArrayListkelas dalam daripada menggunakan yang java.util.ArrayListsatu dan mengapa tidak memiliki metode add()dan remove()?
Abdul

Koreksi atas komentar saya di atas: memang ada metode adddanremove
Abdul

1
@Abdul Karena tidak ada yang namanya ukuran tetap java.util.ArrayList. Anda menginginkan implementasi Listyang memunculkan pengecualian jika Anda melakukan sesuatu yang ilegal dengannya (seperti menambah atau menghapus), dan ArrayListtidak memenuhi persyaratan itu.
Etienne de Martel

@Abdul Arrays.asListbaru saja membuat pembungkus List. Tapi itu masih a java.util.List, jadi harus punya metode itu. Tetapi mereka tidak dapat diterapkan karena itu akan mengarah pada pembuatan larik baru dengan ukuran berbeda. Yang tidak bisa dilakukan karena modifikasi yang masih bisa Anda lakukan bisa dilakukan melalui List yang dikembalikan dan larik asli. Ini tidak akan mungkin jika List yang dikembalikan bisa berubah sehingga pada dasarnya akan membuang referensi array asli.
Adam Hošek

13

Yup, Arrays.asList(..)adalah koleksi yang tidak bisa diperluas atau dikecilkan (karena didukung oleh larik asli, dan tidak bisa diubah ukurannya).

Jika Anda ingin menghapus elemen, buat new ArrayList(Arrays.asList(..)atau hapus elemen langsung dari array (itu akan kurang efisien dan lebih sulit untuk ditulis)


+1 Jawaban ini adalah satu-satunya jawaban yang benar: Arrays.asList () mengembalikan daftar yang tidak dapat diubah - itulah yang membuat pengecualian. Ini tidak ada hubungannya dengan "didukung oleh array" dll ... semua ArrayList didukung oleh array - masalah besar.
Bohemian

1
Tetapi jika Anda membaca lebih jauh ke dalam dokumen, Anda akan menyadari bahwa itu sebenarnya tidak dapat dimodifikasi ... "Mengembalikan daftar ukuran tetap yang didukung oleh larik yang ditentukan. (Perubahan pada daftar yang dikembalikan" tuliskan "ke larik .) "-1, Etienne benar.
Steven Schlansker

1
@Steven Ya, itulah mengapa dikatakan "ukuran tetap" daripada "tidak dapat dimodifikasi" atau "hanya baca". Sebenarnya, saya akan mengedit jawaban saya sekarang untuk mencerminkannya.
Etienne de Martel

1
@Bohemian, Koleksi yang dikembalikan sebenarnya 'dapat dimodifikasi' karena dimungkinkan untuk memanggil metode 'set'.
javalearner

2
Jika Anda akan memilih nits seperti itu, Anda mungkin juga mengatakan hal-hal yang tidak menyenangkan seperti "itu melempar UnsupportedOperationException karena ada pernyataan UnsupportedOperationException lemparan dalam kode". Konsumen API tidak peduli superkelas AbstractBlah mana yang memberikan pengecualian, mereka peduli apa kontrak dan ekspektasi kelas yang mereka gunakan. Dalam JVM v + 1, sangat mungkin perpustakaan kelas berubah ketika pengecualian dilemparkan - tetapi kontrak tidak akan berubah.
Steven Schlansker

7

Begitulah cara Array.asList()kerjanya, karena didukung langsung oleh array. Untuk mendapatkan daftar yang sepenuhnya dapat dimodifikasi, Anda harus mengkloning koleksi tersebut ke dalam koleksi yang Anda buat sendiri.

Collection c = new ArrayList(Arrays.asList(la))

1
Daftar ini dapat dimodifikasi tetapi hanya melalui set (). koleksi yang dikembalikan berukuran tetap.
javalearner

Saya tidak pernah benar-benar mengatakan itu tidak dapat dimodifikasi. Hanya saja untuk mendapatkan daftar (sepenuhnya) yang dapat dimodifikasi, Anda harus menggunakan file ArrayList. Perbedaannya mungkin tidak terlalu jelas. :-) Apakah daftar tersebut dapat dimodifikasi atau tidak merupakan pertanyaan definisi, ini adalah "semi-modifiable" tetapi tidak sepenuhnya dapat dimodifikasi dalam pandangan saya.
henko
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.