Punca ralat checkForComodification() boleh diketahui daripada ralat yang dilaporkan Jika anda ingin mengelakkan ralat, anda perlu mengekalkan modCount != expectedModCount sebagai false . list.remove(Object) akan memanggil kaedah fastRemove(int), dan ia pasti akan mengubah suai modCount pada masa ini, dan ralat akan berlaku pada masa ini. Iterator<String> iterator = list.iterator() ; Pelaksanaan kaedah ini adalah untuk mengembalikan kelas dalaman Itr (kelas ini digunakan dalam proses lelaran), tetapi mengapa ini iterator.remove() tidak menyebabkan ralat adalah kerana ia mempunyai sesuatu untuk dilakukan dengan kaedah ini Pelaksanaannya adalah untuk menyemak ArrayList.this.remove sebelum melakukan checkForComodfication sebenar dan membuat remove selepas expectedModCount = modCount supaya tiada ralat berlaku.
Itr.remove Pelaksanaan
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
Jika ada apa-apa yang salah, sila nyatakan @ChaCha哥 @puliuyinyi
Dalam kes urutan tunggal, apabila memadamkan elemen semasa melintasi Senarai, anda mesti menggunakan kaedah alih keluar Iterator dan bukannya kaedah alih keluar Senarai, jika tidak ConcurrentModificationException akan berlaku. Cuba bayangkan jika seorang guru mengira bilangan pelajar dalam keseluruhan kelas, dan jika pelajar tidak mematuhi peraturan dan keluar masuk, pasti guru tidak dapat mengira mereka.
Dalam kes multi-threading, sila rujuk salah satu blog saya: http://xxgblog.com/2016/04/02...
Pertama sekali, ini melibatkan operasi berbilang benang Iterator tidak menyokong operasi berbilang benang Kelas Senarai akan mengekalkan pembolehubah modCount secara dalaman untuk merekodkan bilangan pengubahsuaian Contoh: kod sumber ArrayList
.
protected transient int modCount = 0;
Setiap kali Iterator dijana, Iterator akan merekodkan modCount Setiap kali kaedah seterusnya() dipanggil, rekod akan dibandingkan dengan modCount bagi Senarai kelas luaran Jika didapati tidak sama, a Pengecualian penyuntingan berbilang benang akan dibuang.
Mengapa anda melakukan ini? Pemahaman saya ialah anda mencipta iterator yang berganding rapat dengan kandungan koleksi yang akan dilalui, yang bermaksud bahawa kandungan koleksi yang sepadan dengan iterator ini adalah kandungan semasa saya pasti tidak mahu melakukannya dalam saya isihan gelembung Apabila , masih ada benang yang memasukkan data ke dalam koleksi saya, bukan? Jadi Java menggunakan mekanisme pemprosesan mudah ini untuk menghalang koleksi daripada diubah suai semasa traversal.
Mengenai mengapa memadamkan "1" sudah cukup, sebabnya terletak pada kaedah hasNext() foreach dan iterator Gula sintaksis foreach sebenarnya
while(itr.hasNext()){
itr.next()
}
Jadi setiap gelung akan melaksanakan hasNext() dahulu, jadi lihat bagaimana ArrayList hasNext() ditulis:
public boolean hasNext() {
return cursor != size;
}
kursor ialah pembolehubah yang digunakan untuk menandakan kedudukan iterator Pembolehubah bermula dari 0 dan melakukan operasi +1 setiap kali seterusnya dipanggil, jadi: Selepas kod anda memadamkan "1", saiz=1, kursor =1, pada masa ini hasNext() mengembalikan false dan menamatkan gelung, jadi iterator anda tidak memanggil di sebelah untuk mencari elemen kedua, jadi tidak ada cara untuk mengesan modCount, jadi tidak akan ada pengecualian pengubahsuaian berbilang benang tetapi apabila Apabila anda memadamkan "2", iterator memanggil seterusnya dua kali Pada masa ini, saiz=1, kursor=2, dan hasNext() kembali benar, jadi iterator secara bodoh memanggil next() sekali lagi, yang juga mencetuskan If. modCount tidak sama, pengecualian pengubahsuaian berbilang benang akan dilemparkan.
Apabila set anda mempunyai tiga elemen, anda akan mendapati bahawa pemadaman "1" akan membuang pengecualian, tetapi pemadaman "2" tidak akan menjadi masalah Sebabnya adalah berkaitan dengan pelaksanaan program di atas Pesanan adalah konsisten .
Oleh kerana nombor dalam koleksi berubah apabila anda menambah atau memadam elemen, masalah mungkin berlaku semasa merentasi Contohnya, jika koleksi mempunyai 10 elemen, ia harus dilalui 10 kali Apabila anda Jika elemen ditambah atau dipadam. bilangan traversal tidak betul, jadi ralat akan dilaporkan
ArrayList tidak selamat untuk benang, yang bermaksud anda mengubah suai Senarai semasa melintasi. ArrayList akan membuang pengecualian pengubahsuaian serentak dalam kes ini.
Punca ralat
checkForComodification()
boleh diketahui daripada ralat yang dilaporkan Jika anda ingin mengelakkan ralat, anda perlu mengekalkanmodCount != expectedModCount
sebagaifalse
.list.remove(Object)
akan memanggil kaedahfastRemove(int)
, dan ia pasti akan mengubah suaimodCount
pada masa ini, dan ralat akan berlaku pada masa ini.Iterator<String> iterator = list.iterator()
; Pelaksanaan kaedah ini adalah untuk mengembalikan kelas dalamanItr
(kelas ini digunakan dalam proses lelaran), tetapi mengapa iniiterator.remove()
tidak menyebabkan ralat adalah kerana ia mempunyai sesuatu untuk dilakukan dengan kaedah ini Pelaksanaannya adalah untuk menyemakArrayList.this.remove
sebelum melakukancheckForComodfication
sebenar dan membuatremove
selepasexpectedModCount = modCount
supaya tiada ralat berlaku.Itr.remove
PelaksanaanJika ada apa-apa yang salah, sila nyatakan @ChaCha哥 @puliuyinyi
Dalam kes urutan tunggal, apabila memadamkan elemen semasa melintasi Senarai, anda mesti menggunakan kaedah alih keluar Iterator dan bukannya kaedah alih keluar Senarai, jika tidak ConcurrentModificationException akan berlaku. Cuba bayangkan jika seorang guru mengira bilangan pelajar dalam keseluruhan kelas, dan jika pelajar tidak mematuhi peraturan dan keluar masuk, pasti guru tidak dapat mengira mereka.
Dalam kes multi-threading, sila rujuk salah satu blog saya: http://xxgblog.com/2016/04/02...
Pertama sekali, ini melibatkan operasi berbilang benang Iterator tidak menyokong operasi berbilang benang Kelas Senarai akan mengekalkan pembolehubah modCount secara dalaman untuk merekodkan bilangan pengubahsuaian
.Contoh: kod sumber ArrayList
Setiap kali Iterator dijana, Iterator akan merekodkan modCount Setiap kali kaedah seterusnya() dipanggil, rekod akan dibandingkan dengan modCount bagi Senarai kelas luaran Jika didapati tidak sama, a Pengecualian penyuntingan berbilang benang akan dibuang.
Mengapa anda melakukan ini? Pemahaman saya ialah anda mencipta iterator yang berganding rapat dengan kandungan koleksi yang akan dilalui, yang bermaksud bahawa kandungan koleksi yang sepadan dengan iterator ini adalah kandungan semasa saya pasti tidak mahu melakukannya dalam saya isihan gelembung Apabila , masih ada benang yang memasukkan data ke dalam koleksi saya, bukan? Jadi Java menggunakan mekanisme pemprosesan mudah ini untuk menghalang koleksi daripada diubah suai semasa traversal.
Mengenai mengapa memadamkan "1" sudah cukup, sebabnya terletak pada kaedah hasNext() foreach dan iterator Gula sintaksis foreach sebenarnya
Jadi setiap gelung akan melaksanakan hasNext() dahulu, jadi lihat bagaimana ArrayList hasNext() ditulis:
kursor ialah pembolehubah yang digunakan untuk menandakan kedudukan iterator Pembolehubah bermula dari 0 dan melakukan operasi +1 setiap kali seterusnya dipanggil, jadi:
Selepas kod anda memadamkan "1", saiz=1, kursor =1, pada masa ini hasNext() mengembalikan false dan menamatkan gelung, jadi iterator anda tidak memanggil di sebelah untuk mencari elemen kedua, jadi tidak ada cara untuk mengesan modCount, jadi tidak akan ada pengecualian pengubahsuaian berbilang benang
tetapi apabila Apabila anda memadamkan "2", iterator memanggil seterusnya dua kali Pada masa ini, saiz=1, kursor=2, dan hasNext() kembali benar, jadi iterator secara bodoh memanggil next() sekali lagi, yang juga mencetuskan If. modCount tidak sama, pengecualian pengubahsuaian berbilang benang akan dilemparkan.
Apabila set anda mempunyai tiga elemen, anda akan mendapati bahawa pemadaman "1" akan membuang pengecualian, tetapi pemadaman "2" tidak akan menjadi masalah Sebabnya adalah berkaitan dengan pelaksanaan program di atas Pesanan adalah konsisten .
Oleh kerana nombor dalam koleksi berubah apabila anda menambah atau memadam elemen, masalah mungkin berlaku semasa merentasi Contohnya, jika koleksi mempunyai 10 elemen, ia harus dilalui 10 kali Apabila anda Jika elemen ditambah atau dipadam. bilangan traversal tidak betul, jadi ralat akan dilaporkan
Hanya padamkannya dalam susunan terbalik Bagaimanapun, cuba untuk tidak mengalih keluar senarai itu. Anda boleh menambah tag padam
Penerangan kuning dalam dokumen sangat menarik.
Anda masih perlu melihat kod sumber
ArrayList
untuk ini, anda akan mengetahuinya sepintas lalu.Hanya padamkannya dalam susunan terbalik
ArrayList tidak selamat untuk benang, yang bermaksud anda mengubah suai Senarai semasa melintasi.
ArrayList akan membuang pengecualian pengubahsuaian serentak dalam kes ini.