Java Academy · Pelajaran

Iterator Gagal Cepat berbanding Selamat Gagal

Fahami ConcurrentModificationException, tingkah laku gagal cepat dan masa untuk menggunakan iterator petikan.

Pelajaran 4 daripada 414 langkah

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 results

Pembuangan 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 copy

Iterator 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 consistent

Collections.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 thread

Corak 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
Percuma untuk bermula

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

  1. Kontrak Iterable dan Iterator
  2. Melaksanakan Iterator Tersuai
  3. ListIterator dan Rentasan Dua Hala
  4. Iterator Gagal Cepat berbanding Selamat Gagal
← Kembali ke Java Academy