Iterator Gagal Cepat berbanding Selamat Gagal
Fahami ConcurrentModificationException, tingkah laku gagal cepat dan masa untuk menggunakan iterator petikan.
Iterator Gagal Cepat berbanding Selamat Gagal ialah pelajaran Java Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Java Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Java Academy merangkumi sejumlah 4 pelajaran.
Iterator Gagal Pantas berbanding Gagal Selamat
Iterator Java dikategorikan berdasarkan kelakuannya apabila koleksi asas diubah semasa lelaran: iterator gagal pantas terus melontarkan ralat; iterator gagal selamat meneruskan lelaran pada salinan keadaan.
Iterator Gagal Pantas
Kebanyakan koleksi Java standard (ArrayList, HashMap, TreeSet) menggunakan iterator gagal pantas. Iterator ini menjejaki modCount — pembilang mutasi. Sebarang pengubahsuaian struktur semasa lelaran mencetuskan ConcurrentModificationException.
import java.util.*;
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
try {
for (String s : list) {
list.add("x"); // structural modification — throws!
}
} catch (ConcurrentModificationException e) {
System.out.println("ConcurrentModificationException caught!");
}
// Same for HashMap, TreeMap, HashSet, etc.Sebab Iterator Gagal Pantas Wujud
Kelakuan gagal pantas ialah bantuan penyahpepijatan — ia mendedahkan pepijat dengan segera dan bukannya membenarkan lelaran diteruskan dengan keadaan yang rosak. Alternatifnya, iaitu kerosakan senyap, jauh lebih sukar untuk dinyahpepijat.
// modCount is incremented on every structural change
// (add, remove, clear on ArrayList)
// Iterator records modCount on creation
// On each next(), Iterator checks: if current modCount != expected, throw CME
// This detects bugs like:
List<Integer> nums = new ArrayList<>(List.of(1,2,3,4,5));
for (Integer n : nums) {
if (n == 3) nums.remove(n); // bug caught immediately
}
// ConcurrentModificationException — not silent wrong resultsPembuangan Selamat: Iterator.remove()
Satu-satunya pengubahsuaian yang selamat semasa lelaran berasaskan Iterator ialah Iterator.remove() — kaedah ini membuang elemen terakhir yang dikembalikan dan mengemas kini modCount.
List<Integer> nums = new ArrayList<>(List.of(1,2,3,4,5,6));
Iterator<Integer> it = nums.iterator();
while (it.hasNext()) {
int n = it.next();
if (n % 2 == 0) it.remove(); // safe: updates modCount
}
System.out.println(nums); // [1, 3, 5]removeIf: Alternatif Moden
Java 8 menambahkan removeIf(Predicate) pada Collection — cara yang lebih kemas untuk membuang elemen yang sepadan dengan syarat tanpa mengurus iterator secara manual.
List<String> names = new ArrayList<>(List.of("Alice", "Bob", "Ann", "Charlie"));
// Modern: removeIf handles iteration internally
names.removeIf(name -> name.startsWith("A"));
System.out.println(names); // [Bob, Charlie]
// Equivalent but verbose iterator approach:
Iterator<String> it = names.iterator();
while (it.hasNext()) {
if (it.next().startsWith("A")) it.remove();
}Iterator Gagal Selamat: CopyOnWriteArrayList
CopyOnWriteArrayList menggunakan iterator gagal selamat. Iterator ini melakukan lelaran pada salinan keadaan yang diambil ketika iterator dicipta — pengubahsuaian tidak menjejaskan lelaran yang sedang berlangsung.
import java.util.concurrent.CopyOnWriteArrayList;
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.addAll(List.of("a", "b", "c"));
for (String s : list) {
list.add("x"); // no ConcurrentModificationException!
System.out.print(s + " "); // prints a, b, c (snapshot)
}
System.out.println();
System.out.println(list); // [a, b, c, x, x, x] — modified copyIterator ConcurrentHashMap
ConcurrentHashMap menggunakan iterator yang konsisten secara lemah — iterator ini mencerminkan keadaan pada suatu ketika semasa atau selepas iterator dicipta, tiada CME dilontarkan dan kemas kini serentak mungkin dilihat atau tidak dilihat.
import java.util.concurrent.ConcurrentHashMap;
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("a", 1); map.put("b", 2); map.put("c", 3);
for (Map.Entry<String, Integer> e : map.entrySet()) {
map.put("d", 4); // no CME — weakly consistent
System.out.println(e.getKey() + "=" + e.getValue());
}
// May or may not print "d=4" — weakly consistentCollections.synchronizedList
Collections.synchronizedList BUKAN gagal selamat — ia masih menggunakan iterator gagal pantas tetapi menyekat capaian serentak. Anda mesti melakukan penyegerakan secara manual semasa lelaran.
import java.util.*;
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
syncList.addAll(List.of("a", "b", "c"));
// Must synchronize during iteration!
synchronized (syncList) {
for (String s : syncList) {
System.out.println(s);
}
}
// Without the synchronized block, CME is still possible from another threadCorak Iterator Salinan Keadaan
Cipta salinan keadaan secara manual untuk melakukan lelaran dengan selamat pada koleksi boleh ubah tanpa penyegerakan.
import java.util.*;
List<String> original = new ArrayList<>(List.of("a", "b", "c"));
// Take a snapshot copy before iterating
List<String> snapshot = List.copyOf(original);
for (String s : snapshot) {
// Safe to modify original during snapshot iteration
original.remove(s);
System.out.println("Removed: " + s);
}
System.out.println(original); // []Pertukaran CopyOnWrite
CopyOnWriteArrayList selamat daripada kegagalan tetapi mahal untuk operasi penulisan. Setiap mutasi mencipta salinan penuh.
- Sesuai untuk: banyak bacaan, penulisan yang jarang berlaku (senarai pendengar peristiwa)
- Tidak sesuai untuk: mutasi yang kerap, koleksi yang besar
Ringkasan: Gagal Pantas berbanding Gagal Selamat
Ringkasan perbandingan:
- Gagal pantas: ArrayList, HashMap, TreeMap — melontarkan CME apabila berlaku pengubahsuaian, dengan semakan modCount
- Gagal selamat/konsisten secara lemah: ConcurrentHashMap, CopyOnWriteArrayList — tiada CME, melakukan lelaran pada salinan keadaan atau data serentak
- Kaedah pengubahsuaian selamat: Iterator.remove(), removeIf(), replaceAll()
Amali: Pembersihan Sesi Tamat Tempoh
Membuang sesi yang telah tamat tempoh dengan selamat daripada senarai serentak menggunakan corak yang sesuai.
import java.util.*;
import java.util.concurrent.*;
class SessionManager {
private final CopyOnWriteArrayList<Session> sessions = new CopyOnWriteArrayList<>();
record Session(String id, long expiresAt) {
boolean isExpired() { return System.currentTimeMillis() > expiresAt; }
}
void add(Session s) { sessions.add(s); }
// Safe to call from multiple threads while iterating
void purgeExpired() {
sessions.removeIf(Session::isExpired);
}
List<Session> active() {
return sessions.stream().filter(s -> !s.isExpired()).toList();
}
}Semakan Pantas
Apakah pengecualian yang dilontarkan apabila ArrayList diubah semasa lelaran?
Imbas Kembali: Iterator Gagal Pantas berbanding Gagal Selamat
Perkara penting:
- Iterator gagal pantas (ArrayList, HashMap) melontarkan ConcurrentModificationException apabila berlaku pengubahsuaian serentak
- Iterator gagal selamat (CopyOnWriteArrayList, ConcurrentHashMap) membenarkan pengubahsuaian tanpa melontarkan pengecualian
- Iterator.remove() ialah satu-satunya cara yang selamat untuk membuang elemen semasa lelaran gagal pantas
- removeIf() ialah alternatif moden dan lebih kemas berbanding Iterator.remove() manual
- CopyOnWriteArrayList: selamat untuk senario yang banyak membaca tetapi jarang menulis
- ConcurrentHashMap: konsisten secara lemah — tiada CME, pengubahsuaian serentak mungkin dilihat atau tidak dilihat
Pelajari Java dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 104
- Pelajaran
- 374
Soalan Lazim
Adakah pelajaran “Iterator Gagal Cepat berbanding Selamat Gagal” percuma?
Ya — teks penuh “Iterator Gagal Cepat berbanding Selamat Gagal” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Java Academy, tingkat taraf kepada CoddyKit PRO. Kursus Java Academy merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Iterator Gagal Cepat berbanding Selamat Gagal”?
Fahami ConcurrentModificationException, tingkah laku gagal cepat dan masa untuk menggunakan iterator petikan. Anda berlatih Java Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Java Academy?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Java Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.
Berapa lamakah pelajaran “Iterator Gagal Cepat berbanding Selamat Gagal” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Java Academy ini?
Ya. Setiap pelajaran Java Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Kontrak Iterable dan Iterator
- Melaksanakan Iterator Tersuai
- ListIterator dan Rentasan Dua Hala
- Iterator Gagal Cepat berbanding Selamat Gagal