Catatan: Saya mengetahui Iterator#remove()
metode ini.
Dalam contoh kode berikut, saya tidak mengerti mengapa metode List.remove
in main
melempar ConcurrentModificationException
, tetapi tidak dalam remove
metode.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
java
list
concurrentmodification
foreach
Bhesh Gurung
sumber
sumber
Iterator#remove()
. Mengapa kamu melakukannya dengan cara ini?ConcurrentModificationException
dan yang lainnya tidak.return;
ke dalam loop.Jawaban:
Inilah sebabnya: Seperti yang dikatakan dalam Javadoc:
Pemeriksaan ini dilakukan dalam
next()
metode iterator (seperti yang Anda lihat dengan stacktrace). Tetapi kita akan mencapainext()
metode hanya jikahasNext()
disampaikan benar, yang disebut oleh masing-masing untuk memeriksa apakah batas terpenuhi. Dalam metode penghapusan Anda, ketikahasNext()
memeriksa apakah perlu mengembalikan elemen lain, ia akan melihat bahwa ia mengembalikan dua elemen, dan sekarang setelah satu elemen dihapus daftar hanya berisi dua elemen. Jadi semuanya sangat bagus dan kita selesai dengan iterasi. Pemeriksaan untuk modifikasi bersamaan tidak terjadi, karena hal ini dilakukan dalamnext()
metode yang tidak pernah disebut.Selanjutnya kita sampai pada loop kedua. Setelah kami menghapus angka kedua metode hasNext akan memeriksa lagi jika dapat mengembalikan lebih banyak nilai. Sudah mengembalikan dua nilai, tetapi daftar sekarang hanya berisi satu. Tetapi kode di sini adalah:
1! = 2, jadi kami melanjutkan ke
next()
metode, yang sekarang menyadari bahwa seseorang telah mengacaukan daftar dan mengeluarkan pengecualian.Semoga itu membersihkan pertanyaan Anda.
Ringkasan
List.remove()
tidak akan membuangConcurrentModificationException
ketika menghapus elemen terakhir kedua dari daftar.sumber
Salah satu cara untuk menanganinya untuk menghapus sesuatu dari salinan
Collection
(bukan Koleksi itu sendiri), jika berlaku.Clone
koleksi asli untuk membuat salinan via aConstructor
.Untuk kasus spesifik Anda, pertama, saya tidak berpikir
final
adalah cara untuk pergi mengingat Anda berniat untuk mengubah daftar pernyataan terakhirJuga pertimbangkan untuk memodifikasi salinan daripada daftar aslinya.
sumber
Metode forward / iterator tidak berfungsi saat menghapus item. Anda dapat menghapus elemen tanpa kesalahan, tetapi Anda akan mendapatkan kesalahan runtime ketika Anda mencoba mengakses item yang dihapus. Anda tidak dapat menggunakan iterator karena seperti yang ditunjukkan oleh pushy akan menyebabkan ConcurrentModificationException, jadi gunakan regular untuk loop, tetapi mundurlah.
Sebuah solusi:
Lintasi array dalam urutan terbalik jika Anda akan menghapus elemen daftar. Cukup dengan menelusuri kembali daftar Anda menghindari mengunjungi item yang telah dihapus, yang menghilangkan pengecualian.
sumber
Cuplikan ini akan selalu menampilkan ConcurrentModificationException.
Aturannya adalah "Anda tidak boleh memodifikasi (menambah atau menghapus elemen dari daftar) saat iterasi menggunakan Iterator (yang terjadi ketika Anda menggunakan untuk-setiap loop)".
JavaDocs:
Iterator yang dikembalikan oleh iterator dan metode listIterator kelas ini gagal-cepat: jika daftar diubah secara struktural setiap saat setelah iterator dibuat, dengan cara apa pun kecuali melalui iterator sendiri yang menghapus atau menambahkan metode, iterator akan membuang ConcurrentModificationException.
Karenanya, jika Anda ingin memodifikasi daftar (atau koleksi apa pun secara umum), gunakan iterator, karena kemudian menyadari modifikasi dan karenanya mereka akan ditangani dengan benar.
Semoga ini membantu.
sumber
Saya memiliki masalah yang sama tetapi jika saya menambahkan elemen en ke dalam daftar iterated. Saya membuatnya seperti ini
Sekarang semuanya berjalan dengan baik karena Anda tidak membuat iterator di daftar Anda, Anda mengulanginya "secara manual". Dan kondisi
i < integerList.size()
tidak akan pernah membodohi Anda karena ketika Anda menghapus / menambahkan sesuatu ke dalam ukuran Daftar dari penurunan / kenaikan Daftar.Semoga ini bisa membantu, bagi saya itu solusinya.
sumber
Jika Anda menggunakan koleksi copy-on-write itu akan berfungsi; namun ketika Anda menggunakan list.iterator (), Iterator yang dikembalikan akan selalu merujuk koleksi elemen seperti ketika (seperti di bawah) list.iterator () dipanggil, bahkan jika utas lain memodifikasi koleksi. Metode mutasi apa pun yang dipanggil pada Iterator atau ListIterator berbasis copy-on-write (seperti menambah, mengatur, atau menghapus) akan melempar UnsupportedOperationException.
sumber
Ini berjalan dengan baik di Java 1.6
~% javac RemoveListElementDemo.java
~% java RemoveListElementDemo
~% cat RemoveListElementDemo.java
~%
sumber
Dalam kasus saya, saya melakukannya seperti ini:
sumber
Ubah Iterator
for each
menjadifor loop
solusi.Dan Alasannya adalah:
--Documents Java yang dirujuk.
sumber
Periksa pembuat kode Anda ....
Dalam metode utama Anda mencoba untuk menghapus elemen ke-4 yang tidak ada di sana dan karenanya kesalahan. Dalam metode hapus () Anda mencoba menghapus elemen ke-3 yang ada dan karenanya tidak ada kesalahan.
sumber
2
dan3
bukan indeks untuk daftar, tetapi elemen. Kedua logika penghapusan memeriksaequals
terhadap elemen daftar, bukan indeks elemen. Lebih jauh lagi, jika itu terkait dengan indeks, itu akan menjadiIndexOutOfBoundsException
, tidakConcurrentModificationException
.