Saya punya kode ini:
public static String SelectRandomFromTemplate(String template,int count) {
String[] split = template.split("|");
List<String> list=Arrays.asList(split);
Random r = new Random();
while( list.size() > count ) {
list.remove(r.nextInt(list.size()));
}
return StringUtils.join(list, ", ");
}
Saya mendapatkan ini:
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): java.lang.UnsupportedOperationException
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): at java.util.AbstractList.remove(AbstractList.java:645)
Bagaimana ini cara yang benar? Java.15
Jawaban:
Beberapa masalah dengan kode Anda:
Saat
Arrays.asList
mengembalikan daftar ukuran tetapDari API:
Anda tidak bisa
add
melakukannya; kamu tidak bisaremove
dari itu. Anda tidak dapat secara struktural memodifikasiList
.Memperbaiki
Buat
LinkedList
, yang mendukung lebih cepatremove
.Saat
split
mengambil regexDari API:
|
adalah metacharacter regex; jika Anda ingin membagi pada literal|
, Anda harus menghindarinya\|
, yang seperti string Java literal"\\|"
.Memperbaiki:
Pada algoritma yang lebih baik
Alih-alih memanggil
remove
satu per satu dengan indeks acak, lebih baik untuk menghasilkan angka acak yang cukup dalam rentang, dan kemudian melintasiList
sekali denganlistIterator()
, memanggilremove()
pada indeks yang sesuai. Ada pertanyaan tentang stackoverflow tentang cara menghasilkan angka acak tetapi berbeda dalam rentang tertentu.Dengan ini, algoritma Anda akan menjadi
O(N)
.sumber
Random
setiap kali. Jadikanstatic
ladang dan benih hanya sekali.Yang ini telah membakar saya beberapa kali.
Arrays.asList
membuat daftar yang tidak dapat dimodifikasi. Dari Javadoc: Mengembalikan daftar ukuran tetap yang didukung oleh array yang ditentukan.Buat daftar baru dengan konten yang sama:
Ini akan menghasilkan sedikit sampah tambahan, tetapi Anda dapat mengubahnya.
sumber
Mungkin karena Anda bekerja dengan pembungkus yang tidak dapat dimodifikasi .
Ubah baris ini:
ke baris ini:
sumber
unmodifiable
danimmutable
.unmodifiable
berarti tepat "dapat dimodifikasi, tetapi tidak secara struktural".unmodifiableList
pembungkus dan mencobaset
; itu melemparUnsupportedOperationException
. Saya cukup yakinCollections.unmodifiable*
benar - benar berarti kekekalan penuh, bukan hanya struktural.Saya pikir mengganti itu:
dengan
menyelesaikan masalah.
sumber
Daftar yang dikembalikan oleh
Arrays.asList()
mungkin tidak berubah. Bisakah kamu mencobasumber
Cukup baca JavaDoc untuk metode asList:
Ini dari Java 6 tetapi sepertinya sama untuk android java.
EDIT
Jenis daftar yang dihasilkan adalah
Arrays.ArrayList
, yang merupakan kelas pribadi di dalam Arrays.class. Secara praktis, ini hanyalah tampilan daftar pada array yang telah Anda lewatiArrays.asList
. Dengan konsekuensi: jika Anda mengubah array, daftar juga berubah. Dan karena sebuah array tidak dapat diubah ukurannya, hapus dan tambahkan operasi harus tidak didukung.sumber
Arrays.asList () mengembalikan daftar yang tidak memungkinkan operasi memengaruhi ukurannya (perhatikan bahwa ini tidak sama dengan "tidak dapat dimodifikasi").
Anda dapat melakukan
new ArrayList<String>(Arrays.asList(split));
untuk membuat salinan nyata, tetapi melihat apa yang Anda coba lakukan, berikut ini adalah saran tambahan (Anda memilikiO(n^2)
algoritma tepat di bawahnya).Anda ingin menghapus
list.size() - count
(sebut inik
) elemen acak dari daftar.k
Pilih saja elemen acak dan tukarkan dengan posisi akhir daftar, lalu hapus seluruh rentang itu (misalnya menggunakan subList () dan hapus () pada itu). Itu akan mengubahnya menjadiO(n)
algoritma ramping dan rata-rata (O(k)
lebih tepat).Pembaruan : Sebagaimana dicatat di bawah ini, algoritma ini hanya masuk akal jika elemen-elemennya tidak berurutan, misalnya jika Daftar tersebut mewakili Tas. Jika, di sisi lain, Daftar memiliki urutan yang berarti, algoritma ini tidak akan melestarikannya (algoritma polygenelubricants 'sebaliknya akan).
Pembaruan 2 : Jadi dalam retrospeksi, algoritma yang lebih baik (linier, mempertahankan urutan, tetapi dengan O (n) angka acak) akan menjadi seperti ini:
sumber
ArrayList
. Jauh lebih sederhana dari saran saya. Saya pikir itu akan menghasilkan penataan ulang elemen.Saya punya solusi lain untuk masalah itu:
kerjakan
newList
;)sumber
UnsupportedOperationException ini datang ketika Anda mencoba untuk melakukan beberapa operasi pada koleksi di mana itu tidak diizinkan dan dalam kasus Anda, Ketika Anda memanggilnya
Arrays.asList
tidak mengembalikan ajava.util.ArrayList
. Ini mengembalikan daftarjava.util.Arrays$ArrayList
yang tidak dapat diubah. Anda tidak dapat menambahkannya dan Anda tidak dapat menghapusnya.sumber
Ya, aktif
Arrays.asList
, mengembalikan daftar ukuran tetap.Selain menggunakan daftar tertaut, cukup gunakan
addAll
daftar metode.Contoh:
sumber
Menggantikan
untuk
atau
atau
atau (Lebih baik untuk elemen Hapus)
sumber
Arraylist narraylist = Arrays.asList (); // Mengembalikan arraylist yang tidak dapat diubah Untuk menjadikannya solusi yang bisa berubah-ubah adalah: Arraylist narraylist = new ArrayList (Arrays.asList ());
sumber
Berikut ini cuplikan kode dari Array
jadi apa yang terjadi adalah bahwa ketika metode asList dipanggil maka ia mengembalikan daftar versi kelas privat statis yang tidak menimpa menambahkan funcion dari AbstractList untuk menyimpan elemen dalam array. Jadi secara default menambahkan metode dalam daftar abstrak melempar pengecualian.
Jadi ini bukan daftar array biasa.
sumber
Anda tidak dapat menghapus, juga tidak dapat menambahkan ke daftar Array ukuran tetap.
Tetapi Anda dapat membuat sublist Anda dari daftar itu.
list = list.subList(0, list.size() - (list.size() - count));
* Cara lain adalah
ini akan membuat ArrayList yang bukan ukuran tetap seperti Arrays.asList
sumber
Arrays.asList()
menggunakan array ukuran tetap secara internal.Anda tidak dapat menambahkan atau menghapus secara dinamis dari ini
Arrays.asList()
Gunakan ini
Di dalam
narraylist
Anda dapat dengan mudah menambah atau menghapus item.sumber
Membuat daftar baru dan mengisi nilai-nilai yang valid dalam daftar baru berhasil untuk saya.
Kesalahan melempar kode -
Setelah memperbaiki -
sumber