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 resultsPenghapusan 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 copyIterator 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 consistentCollections.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 threadPola 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
- Kontrak Iterable dan Iterator
- Mengimplementasikan Iterator Kustom
- ListIterator dan Traversal Dua Arah
- Iterator Fail-Fast vs Fail-Safe