0Pricing
Java Academy · Pelajaran

Iterator Fail-Fast vs Fail-Safe

Pahami ConcurrentModificationException, perilaku fail-fast, dan kapan menggunakan iterator snapshot.

Iterator Fail-Fast vs Fail-Safe adalah pelajaran Java Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Java Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Java Academy mencakup 4 pelajaran total.

Iterator Gagal-Cepat vs Gagal-Aman

Iterator Java dikategorikan berdasarkan perilakunya ketika koleksi dasar dimodifikasi selama iterasi: iterator gagal-cepat langsung melempar pengecualian; iterator gagal-aman melanjutkan iterasi pada salinan keadaan.

Iterator Gagal-Cepat

Sebagian besar koleksi Java standar (ArrayList, HashMap, TreeSet) menggunakan iterator gagal-cepat. Iterator tersebut melacak modCount — penghitung mutasi. Setiap modifikasi struktural selama iterasi memicu 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.

Alasan Iterator Gagal-Cepat Ada

Perilaku gagal-cepat membantu proses penelusuran kesalahan — perilaku ini segera menampilkan bug, alih-alih membiarkan iterasi berlanjut dengan keadaan yang rusak. Alternatifnya, yaitu kerusakan diam-diam, jauh lebih sulit untuk ditelusuri.

// 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

Penghapusan Aman: Iterator.remove()

Satu-satunya modifikasi yang aman selama iterasi berbasis Iterator adalah Iterator.remove() — metode ini menghapus elemen terakhir yang dikembalikan dan memperbarui 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 Modern

Java 8 menambahkan removeIf(Predicate) ke Collection — cara yang lebih bersih untuk menghapus elemen yang cocok dengan suatu kondisi tanpa mengelola 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-Aman: CopyOnWriteArrayList

CopyOnWriteArrayList menggunakan iterator gagal-aman. Iterator tersebut melakukan iterasi pada salinan keadaan yang dibuat saat iterator dibuat — modifikasi tidak memengaruhi iterasi 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 dengan konsistensi lemah — iterator mencerminkan keadaan pada suatu waktu selama atau setelah iterator dibuat, tidak melempar CME, dan mungkin melihat atau tidak melihat pembaruan serentak.

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 iterator gagal-aman — koleksi ini tetap menggunakan iterator gagal-cepat, tetapi memblokir akses serentak. Anda harus melakukan sinkronisasi secara manual selama iterasi.

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

Pola Iterator dengan Salinan Keadaan

Buat salinan keadaan secara manual untuk melakukan iterasi dengan aman pada koleksi yang dapat berubah tanpa sinkronisasi.

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); // []

Kompromi CopyOnWrite

CopyOnWriteArrayList aman dari kegagalan iterasi, tetapi mahal untuk operasi tulis. Setiap mutasi membuat salinan penuh.

  • Cocok untuk: banyak pembacaan, penulisan yang jarang (daftar pemantau peristiwa)
  • Tidak cocok untuk: mutasi yang sering, koleksi berukuran besar

Ringkasan: Gagal-Cepat vs Gagal-Aman

Ringkasan perbandingan:

  • Gagal-cepat: ArrayList, HashMap, TreeMap — melempar CME saat terjadi modifikasi, dengan pemeriksaan modCount
  • Gagal-aman/konsistensi lemah: ConcurrentHashMap, CopyOnWriteArrayList — tidak ada CME, melakukan iterasi pada salinan keadaan atau data yang dimodifikasi secara serentak
  • Metode modifikasi yang aman: Iterator.remove(), removeIf(), replaceAll()

Praktik: Pembersihan Sesi Kedaluwarsa

Menghapus sesi yang kedaluwarsa dengan aman dari list serentak menggunakan pola 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();
    }
}

Pemeriksaan Singkat

Pengecualian apa yang dilempar saat ArrayList dimodifikasi selama iterasi?

Ringkasan: Iterator Gagal-Cepat vs Gagal-Aman

Hal-hal penting:

  • Iterator gagal-cepat (ArrayList, HashMap) melempar ConcurrentModificationException saat terjadi modifikasi serentak
  • Iterator gagal-aman (CopyOnWriteArrayList, ConcurrentHashMap) memungkinkan modifikasi tanpa melempar pengecualian
  • Iterator.remove() adalah satu-satunya cara aman untuk menghapus elemen selama iterasi gagal-cepat
  • removeIf() adalah alternatif modern dan lebih bersih daripada Iterator.remove() manual
  • CopyOnWriteArrayList: aman untuk skenario yang didominasi pembacaan dan jarang melakukan penulisan
  • ConcurrentHashMap: konsistensinya lemah — tidak ada CME, dan mungkin melihat atau tidak melihat modifikasi serentak

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Iterator Fail-Fast vs Fail-Safe” gratis?

Ya — teks lengkap “Iterator Fail-Fast vs Fail-Safe” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Java Academy, upgrade ke CoddyKit PRO. Kursus Java Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Iterator Fail-Fast vs Fail-Safe”?

Pahami ConcurrentModificationException, perilaku fail-fast, dan kapan menggunakan iterator snapshot. Kamu berlatih Java Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Java Academy?

Tidak diperlukan pengalaman sebelumnya. Java Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “Iterator Fail-Fast vs Fail-Safe” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Java Academy ini?

Ya. Setiap pelajaran Java Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Kontrak Iterable dan Iterator
  2. Mengimplementasikan Iterator Kustom
  3. ListIterator dan Traversal Dua Arah
  4. Iterator Fail-Fast vs Fail-Safe
← Kembali ke Java Academy