Table of Contents
- Introduction to Iterators
- Iterator Interface
- ListIterator Interface
- Comparison: Iterator vs ListIterator
- Implementation Examples
- Fail-Fast vs Fail-Safe Iterators
- Custom Iterator Implementation
- Best Practices
- Real-World Examples
Introduction to Iterators
Iterators provide a way to traverse through collections in Java. They offer a standardized approach to access elements sequentially without exposing the underlying collection structure.
Why Use Iterators?
- Uniform access to different collection types
- Safe element removal during iteration
- Bidirectional traversal (with ListIterator)
- Separation of concerns between traversal logic and collection implementation
Iterator Interface
Basic Iterator Methods
public interface Iterator<E> { boolean hasNext(); // Returns true if more elements exist E next(); // Returns the next element void remove(); // Removes the last element returned by next() } Basic Iterator Usage
import java.util.*; public class BasicIteratorDemo { public static void main(String[] args) { List<String> fruits = new ArrayList<>(); fruits.add("Apple"); fruits.add("Banana"); fruits.add("Orange"); fruits.add("Mango"); System.out.println("=== Basic Iterator Traversal ==="); // Get iterator instance Iterator<String> iterator = fruits.iterator(); // Traverse using iterator while (iterator.hasNext()) { String fruit = iterator.next(); System.out.println("Fruit: " + fruit); } } } Iterator with Removal
import java.util.*; public class IteratorRemovalDemo { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); for (int i = 1; i <= 10; i++) { numbers.add(i); } System.out.println("Original list: " + numbers); // Remove even numbers using iterator Iterator<Integer> iterator = numbers.iterator(); while (iterator.hasNext()) { Integer number = iterator.next(); if (number % 2 == 0) { iterator.remove(); // Safe removal during iteration } } System.out.println("After removing even numbers: " + numbers); } } Iterator with Different Collection Types
import java.util.*; public class IteratorWithCollections { public static void main(String[] args) { System.out.println("=== Iterator with Different Collections ==="); // ArrayList List<String> arrayList = Arrays.asList("A", "B", "C", "D"); System.out.println("ArrayList iteration:"); iterateCollection(arrayList); // HashSet Set<String> hashSet = new HashSet<>(Arrays.asList("X", "Y", "Z")); System.out.println("\nHashSet iteration:"); iterateCollection(hashSet); // LinkedList Queue<String> linkedList = new LinkedList<>(Arrays.asList("P", "Q", "R")); System.out.println("\nLinkedList iteration:"); iterateCollection(linkedList); } public static void iterateCollection(Collection<String> collection) { Iterator<String> iterator = collection.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); } } } ListIterator Interface
ListIterator Methods
public interface ListIterator<E> extends Iterator<E> { // Forward operations (from Iterator) boolean hasNext(); E next(); // Backward operations boolean hasPrevious(); E previous(); // Index operations int nextIndex(); int previousIndex(); // Modification operations void remove(); void set(E e); void add(E e); } Basic ListIterator Usage
import java.util.*; public class BasicListIteratorDemo { public static void main(String[] args) { List<String> colors = new ArrayList<>(); colors.add("Red"); colors.add("Green"); colors.add("Blue"); colors.add("Yellow"); System.out.println("=== ListIterator Bidirectional Traversal ==="); // Get ListIterator ListIterator<String> listIterator = colors.listIterator(); System.out.println("Forward traversal:"); while (listIterator.hasNext()) { String color = listIterator.next(); System.out.println("Color: " + color + " [Index: " + listIterator.nextIndex() + "]"); } System.out.println("\nBackward traversal:"); while (listIterator.hasPrevious()) { String color = listIterator.previous(); System.out.println("Color: " + color + " [Index: " + listIterator.previousIndex() + "]"); } } } ListIterator Modification Operations
import java.util.*; public class ListIteratorModificationDemo { public static void main(String[] args) { List<String> cities = new ArrayList<>(); Collections.addAll(cities, "New York", "London", "Tokyo", "Paris"); System.out.println("Original list: " + cities); ListIterator<String> iterator = cities.listIterator(); // Modify elements during iteration while (iterator.hasNext()) { String city = iterator.next(); if (city.equals("London")) { iterator.set("LONDON"); // Replace element } if (city.equals("Tokyo")) { iterator.add("Sydney"); // Add element after current position } } System.out.println("After modifications: " + cities); // Remove specific elements iterator = cities.listIterator(); while (iterator.hasNext()) { String city = iterator.next(); if (city.length() <= 5) { iterator.remove(); // Remove short city names } } System.out.println("After removal: " + cities); } } Comparison: Iterator vs ListIterator
Feature Comparison Table
| Feature | Iterator | ListIterator |
|---|---|---|
| Traversal Direction | Forward only | Bidirectional |
| Element Access | Sequential | Sequential with indices |
| Element Modification | Remove only | Remove, Add, Set |
| Collection Types | All Collections | Only Lists |
| Index Information | No | Yes (nextIndex, previousIndex) |
Side-by-Side Comparison
import java.util.*; public class IteratorVsListIterator { public static void main(String[] args) { List<String> data = Arrays.asList("A", "B", "C", "D", "E"); System.out.println("=== Iterator vs ListIterator Comparison ==="); // Iterator demonstration System.out.println("\n--- Iterator (Forward only) ---"); Iterator<String> iterator = data.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); } // ListIterator demonstration System.out.println("\n\n--- ListIterator (Bidirectional) ---"); ListIterator<String> listIterator = data.listIterator(); System.out.print("Forward: "); while (listIterator.hasNext()) { System.out.print(listIterator.next() + " "); } System.out.print("\nBackward: "); while (listIterator.hasPrevious()) { System.out.print(listIterator.previous() + " "); } // ListIterator additional features System.out.println("\n\n--- ListIterator Extra Features ---"); listIterator = data.listIterator(); while (listIterator.hasNext()) { String element = listIterator.next(); int nextIndex = listIterator.nextIndex(); System.out.println("Element: " + element + ", Next Index: " + nextIndex); // Modify elements if (element.equals("C")) { listIterator.set("C-MODIFIED"); } } System.out.println("Modified list: " + data); } } Implementation Examples
Practical Iterator Patterns
import java.util.*; public class PracticalIteratorPatterns { // Pattern 1: Filter elements during iteration public static <T> List<T> filterList(List<T> list, java.util.function.Predicate<T> predicate) { List<T> result = new ArrayList<>(); Iterator<T> iterator = list.iterator(); while (iterator.hasNext()) { T element = iterator.next(); if (predicate.test(element)) { result.add(element); } } return result; } // Pattern 2: Transform elements during iteration public static <T, R> List<R> transformList(List<T> list, java.util.function.Function<T, R> function) { List<R> result = new ArrayList<>(); Iterator<T> iterator = list.iterator(); while (iterator.hasNext()) { T element = iterator.next(); result.add(function.apply(element)); } return result; } // Pattern 3: Find element with custom condition public static <T> Optional<T> findElement(List<T> list, java.util.function.Predicate<T> predicate) { Iterator<T> iterator = list.iterator(); while (iterator.hasNext()) { T element = iterator.next(); if (predicate.test(element)) { return Optional.of(element); } } return Optional.empty(); } public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); System.out.println("Original numbers: " + numbers); // Filter even numbers List<Integer> evenNumbers = filterList(numbers, n -> n % 2 == 0); System.out.println("Even numbers: " + evenNumbers); // Transform numbers to their squares List<Integer> squares = transformList(numbers, n -> n * n); System.out.println("Squares: " + squares); // Find first number greater than 5 Optional<Integer> found = findElement(numbers, n -> n > 5); found.ifPresent(n -> System.out.println("First number > 5: " + n)); } } Advanced ListIterator Usage
import java.util.*; public class AdvancedListIteratorDemo { // Reverse a list using ListIterator public static <T> void reverseList(List<T> list) { ListIterator<T> forward = list.listIterator(); ListIterator<T> backward = list.listIterator(list.size()); for (int i = 0; i < list.size() / 2; i++) { T temp = forward.next(); forward.set(backward.previous()); backward.set(temp); } } // Merge two sorted lists public static <T extends Comparable<T>> List<T> mergeSortedLists(List<T> list1, List<T> list2) { List<T> result = new ArrayList<>(); ListIterator<T> iter1 = list1.listIterator(); ListIterator<T> iter2 = list2.listIterator(); T elem1 = iter1.hasNext() ? iter1.next() : null; T elem2 = iter2.hasNext() ? iter2.next() : null; while (elem1 != null || elem2 != null) { if (elem1 == null) { result.add(elem2); elem2 = iter2.hasNext() ? iter2.next() : null; } else if (elem2 == null) { result.add(elem1); elem1 = iter1.hasNext() ? iter1.next() : null; } else if (elem1.compareTo(elem2) <= 0) { result.add(elem1); elem1 = iter1.hasNext() ? iter1.next() : null; } else { result.add(elem2); elem2 = iter2.hasNext() ? iter2.next() : null; } } return result; } // Find all occurrences and their indices public static <T> Map<T, List<Integer>> findElementIndices(List<T> list) { Map<T, List<Integer>> indices = new HashMap<>(); ListIterator<T> iterator = list.listIterator(); while (iterator.hasNext()) { int index = iterator.nextIndex(); T element = iterator.next(); indices.computeIfAbsent(element, k -> new ArrayList<>()).add(index); } return indices; } public static void main(String[] args) { // Test reverse List<String> words = new ArrayList<>(Arrays.asList("A", "B", "C", "D")); System.out.println("Original: " + words); reverseList(words); System.out.println("Reversed: " + words); // Test merge List<Integer> list1 = Arrays.asList(1, 3, 5, 7); List<Integer> list2 = Arrays.asList(2, 4, 6, 8); List<Integer> merged = mergeSortedLists(list1, list2); System.out.println("Merged: " + merged); // Test indices List<String> elements = Arrays.asList("A", "B", "A", "C", "B", "A"); Map<String, List<Integer>> indices = findElementIndices(elements); System.out.println("Element indices: " + indices); } } Fail-Fast vs Fail-Safe Iterators
Fail-Fast Iterators
import java.util.*; public class FailFastIteratorDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); Collections.addAll(list, "A", "B", "C", "D"); System.out.println("=== Fail-Fast Iterator Demo ==="); // This will throw ConcurrentModificationException try { Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println("Processing: " + element); if (element.equals("B")) { list.add("E"); // Structural modification } } } catch (ConcurrentModificationException e) { System.out.println("ConcurrentModificationException caught: " + e.getMessage()); } // Safe way to modify during iteration System.out.println("\n=== Safe Modification ==="); List<String> safeList = new ArrayList<>(); Collections.addAll(safeList, "A", "B", "C", "D"); Iterator<String> safeIterator = safeList.iterator(); List<String> toAdd = new ArrayList<>(); while (safeIterator.hasNext()) { String element = safeIterator.next(); System.out.println("Processing: " + element); if (element.equals("B")) { toAdd.add("E"); // Collect elements to add later } if (element.equals("C")) { safeIterator.remove(); // Safe removal using iterator } } // Add collected elements after iteration safeList.addAll(toAdd); System.out.println("Final list: " + safeList); } } Fail-Safe Iterators (CopyOnWriteArrayList)
import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; public class FailSafeIteratorDemo { public static void main(String[] args) { // CopyOnWriteArrayList is fail-safe List<String> list = new CopyOnWriteArrayList<>(); Collections.addAll(list, "A", "B", "C", "D"); System.out.println("=== Fail-Safe Iterator Demo ==="); Iterator<String> iterator = list.iterator(); // Modify list while iterating (won't throw exception) while (iterator.hasNext()) { String element = iterator.next(); System.out.println("Processing: " + element); if (element.equals("B")) { list.add("E"); // Structural modification list.remove("A"); // Another modification } } System.out.println("List after modifications: " + list); System.out.println("Note: Iterator didn't see the modifications!"); // New iterator will see the changes System.out.println("\nNew iteration with new iterator:"); iterator = list.iterator(); while (iterator.hasNext()) { System.out.println("Element: " + iterator.next()); } } } Concurrent Modification Scenarios
import java.util.*; public class ConcurrentModificationScenarios { public static void main(String[] args) { System.out.println("=== Concurrent Modification Scenarios ==="); List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D")); // Scenario 1: Direct modification - THROWS EXCEPTION try { Iterator<String> iter1 = list.iterator(); while (iter1.hasNext()) { String element = iter1.next(); if (element.equals("B")) { list.remove("B"); // Direct modification } } } catch (ConcurrentModificationException e) { System.out.println("Scenario 1: Direct modification - EXCEPTION"); } // Scenario 2: Iterator removal - WORKS FINE List<String> list2 = new ArrayList<>(Arrays.asList("A", "B", "C", "D")); Iterator<String> iter2 = list2.iterator(); while (iter2.hasNext()) { String element = iter2.next(); if (element.equals("B")) { iter2.remove(); // Iterator removal - SAFE } } System.out.println("Scenario 2: Iterator removal - SUCCESS: " + list2); // Scenario 3: Modification after iterator creation - THROWS EXCEPTION try { List<String> list3 = new ArrayList<>(Arrays.asList("A", "B", "C", "D")); Iterator<String> iter3 = list3.iterator(); list3.add("E"); // Modification after iterator creation iter3.next(); // This will throw exception } catch (ConcurrentModificationException e) { System.out.println("Scenario 3: Modification after iterator - EXCEPTION"); } } } Custom Iterator Implementation
Building a Custom Collection with Iterator
import java.util.*; class FixedSizeCollection<E> implements Iterable<E> { private final E[] elements; private int size; @SuppressWarnings("unchecked") public FixedSizeCollection(int capacity) { this.elements = (E[]) new Object[capacity]; this.size = 0; } public boolean add(E element) { if (size < elements.length) { elements[size++] = element; return true; } return false; } public E get(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException(); } return elements[index]; } public int size() { return size; } @Override public Iterator<E> iterator() { return new FixedSizeIterator(); } // Custom Iterator implementation private class FixedSizeIterator implements Iterator<E> { private int currentIndex = 0; private boolean removeCalled = false; @Override public boolean hasNext() { return currentIndex < size; } @Override public E next() { if (!hasNext()) { throw new NoSuchElementException(); } removeCalled = false; return elements[currentIndex++]; } @Override public void remove() { if (currentIndex == 0 || removeCalled) { throw new IllegalStateException(); } // Shift elements to remove current element for (int i = currentIndex - 1; i < size - 1; i++) { elements[i] = elements[i + 1]; } elements[--size] = null; currentIndex--; removeCalled = true; } } } public class CustomIteratorDemo { public static void main(String[] args) { FixedSizeCollection<String> collection = new FixedSizeCollection<>(5); collection.add("Apple"); collection.add("Banana"); collection.add("Cherry"); collection.add("Date"); System.out.println("=== Custom Iterator Demo ==="); // Using enhanced for-loop (uses our iterator) for (String fruit : collection) { System.out.println("Fruit: " + fruit); } // Using iterator directly System.out.println("\nUsing iterator directly:"); Iterator<String> iterator = collection.iterator(); while (iterator.hasNext()) { String fruit = iterator.next(); System.out.println("Fruit: " + fruit); if (fruit.equals("Banana")) { iterator.remove(); // Use our custom remove } } System.out.println("\nAfter removal:"); for (String fruit : collection) { System.out.println("Fruit: " + fruit); } } } Custom ListIterator Implementation
import java.util.*; class CircularList<E> implements List<E> { private final List<E> elements; public CircularList() { this.elements = new ArrayList<>(); } public CircularList(Collection<? extends E> c) { this.elements = new ArrayList<>(c); } @Override public ListIterator<E> listIterator() { return new CircularListIterator(0); } @Override public ListIterator<E> listIterator(int index) { return new CircularListIterator(index); } // Other List methods would be implemented here... @Override public int size() { return elements.size(); } @Override public boolean isEmpty() { return elements.isEmpty(); } @Override public boolean contains(Object o) { return elements.contains(o); } @Override public Iterator<E> iterator() { return elements.iterator(); } @Override public Object[] toArray() { return elements.toArray(); } @Override public <T> T[] toArray(T[] a) { return elements.toArray(a); } @Override public boolean add(E e) { return elements.add(e); } @Override public boolean remove(Object o) { return elements.remove(o); } @Override public boolean containsAll(Collection<?> c) { return elements.containsAll(c); } @Override public boolean addAll(Collection<? extends E> c) { return elements.addAll(c); } @Override public boolean addAll(int index, Collection<? extends E> c) { return elements.addAll(index, c); } @Override public boolean removeAll(Collection<?> c) { return elements.removeAll(c); } @Override public boolean retainAll(Collection<?> c) { return elements.retainAll(c); } @Override public void clear() { elements.clear(); } @Override public E get(int index) { return elements.get(index); } @Override public E set(int index, E element) { return elements.set(index, element); } @Override public void add(int index, E element) { elements.add(index, element); } @Override public E remove(int index) { return elements.remove(index); } @Override public int indexOf(Object o) { return elements.indexOf(o); } @Override public int lastIndexOf(Object o) { return elements.lastIndexOf(o); } @Override public List<E> subList(int fromIndex, int toIndex) { return elements.subList(fromIndex, toIndex); } // Custom Circular ListIterator private class CircularListIterator implements ListIterator<E> { private int currentPosition; private int lastReturned = -1; private int direction = 0; // 0=initial, 1=forward, -1=backward public CircularListIterator(int index) { this.currentPosition = index % (elements.size() + 1); } @Override public boolean hasNext() { return !elements.isEmpty(); // Always true for circular list } @Override public E next() { if (elements.isEmpty()) { throw new NoSuchElementException(); } E element = elements.get(currentPosition); lastReturned = currentPosition; currentPosition = (currentPosition + 1) % elements.size(); direction = 1; return element; } @Override public boolean hasPrevious() { return !elements.isEmpty(); // Always true for circular list } @Override public E previous() { if (elements.isEmpty()) { throw new NoSuchElementException(); } currentPosition = (currentPosition - 1 + elements.size()) % elements.size(); E element = elements.get(currentPosition); lastReturned = currentPosition; direction = -1; return element; } @Override public int nextIndex() { return currentPosition; } @Override public int previousIndex() { return (currentPosition - 1 + elements.size()) % elements.size(); } @Override public void remove() { if (lastReturned == -1) { throw new IllegalStateException(); } elements.remove(lastReturned); if (lastReturned < currentPosition) { currentPosition--; } currentPosition %= elements.size(); lastReturned = -1; } @Override public void set(E e) { if (lastReturned == -1) { throw new IllegalStateException(); } elements.set(lastReturned, e); } @Override public void add(E e) { elements.add(currentPosition, e); currentPosition++; lastReturned = -1; } } } public class CustomListIteratorDemo { public static void main(String[] args) { CircularList<String> circularList = new CircularList<>( Arrays.asList("A", "B", "C", "D") ); System.out.println("=== Custom Circular ListIterator ==="); ListIterator<String> iterator = circularList.listIterator(); System.out.println("First 10 elements (circular):"); for (int i = 0; i < 10; i++) { System.out.print(iterator.next() + " "); } System.out.println("\n\nPrevious 5 elements:"); for (int i = 0; i < 5; i++) { System.out.print(iterator.previous() + " "); } } } Best Practices
Iterator Best Practices
import java.util.*; public class IteratorBestPractices { // 1. Always check hasNext() before next() public static void safeIteration(List<String> list) { Iterator<String> iterator = list.iterator(); // CORRECT: Check hasNext() first while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); } // INCORRECT: This can throw NoSuchElementException // while (true) { // String element = iterator.next(); // Dangerous! // System.out.println(element); // } } // 2. Use iterator.remove() for safe removal public static void safeRemoval(List<Integer> list) { Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { Integer number = iterator.next(); if (number % 2 == 0) { iterator.remove(); // SAFE: Uses iterator's remove method } } // DANGEROUS: Modifying list directly during iteration // for (Integer number : list) { // if (number % 2 == 0) { // list.remove(number); // ConcurrentModificationException! // } // } } // 3. Use for-each loop when you don't need to remove elements public static void forEachBestPractice(List<String> list) { // GOOD: Simple iteration without removal for (String element : list) { System.out.println(element); } // BETTER: When you need removal capability Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); if (element.startsWith("A")) { iterator.remove(); } } } // 4. Prefer ListIterator for List operations public static void listIteratorBestPractice(List<String> list) { ListIterator<String> listIterator = list.listIterator(); // Bidirectional traversal while (listIterator.hasNext()) { String element = listIterator.next(); if (element.equals("Target")) { // Can go back and modify listIterator.previous(); listIterator.set("Modified Target"); listIterator.next(); } } } // 5. Avoid concurrent modifications public static void avoidConcurrentModification() { List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); // SAFE: Collect modifications and apply later List<String> toRemove = new ArrayList<>(); List<String> toAdd = new ArrayList<>(); for (String element : list) { if (element.equals("B")) { toRemove.add(element); toAdd.add("B-New"); } } list.removeAll(toRemove); list.addAll(toAdd); System.out.println("Safe modification result: " + list); } // 6. Use appropriate iterator for the collection type public static void chooseRightIterator() { List<String> arrayList = new ArrayList<>(); Set<String> hashSet = new HashSet<>(); Map<String, Integer> hashMap = new HashMap<>(); // List: Use ListIterator for bidirectional access ListIterator<String> listIter = arrayList.listIterator(); // Set: Use Iterator (only forward) Iterator<String> setIter = hashSet.iterator(); // Map: Iterate over entrySet, keySet, or values Iterator<Map.Entry<String, Integer>> mapIter = hashMap.entrySet().iterator(); System.out.println("Using appropriate iterators for each collection type"); } public static void main(String[] args) { List<String> sampleList = new ArrayList<>(Arrays.asList("A", "B", "C", "D")); List<Integer> numberList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); safeIteration(sampleList); safeRemoval(numberList); forEachBestPractice(sampleList); listIteratorBestPractice(sampleList); avoidConcurrentModification(); chooseRightIterator(); } } Real-World Examples
Text Processing with Iterators
import java.util.*; public class TextProcessingWithIterators { // Remove duplicate lines while preserving order public static List<String> removeDuplicateLines(List<String> lines) { List<String> result = new ArrayList<>(); Set<String> seen = new HashSet<>(); ListIterator<String> iterator = lines.listIterator(); while (iterator.hasNext()) { String line = iterator.next(); if (!seen.contains(line)) { seen.add(line); result.add(line); } } return result; } // Find and highlight text occurrences public static List<String> highlightText(List<String> lines, String searchText) { List<String> result = new ArrayList<>(); ListIterator<String> iterator = lines.listIterator(); while (iterator.hasNext()) { String line = iterator.next(); if (line.contains(searchText)) { String highlighted = line.replace(searchText, "**" + searchText + "**"); iterator.set(highlighted); // Replace in original list } result.add(line); } return result; } // Merge two documents line by line public static List<String> mergeDocuments(List<String> doc1, List<String> doc2) { List<String> result = new ArrayList<>(); ListIterator<String> iter1 = doc1.listIterator(); ListIterator<String> iter2 = doc2.listIterator(); while (iter1.hasNext() || iter2.hasNext()) { if (iter1.hasNext()) { result.add(iter1.next()); } if (iter2.hasNext()) { result.add(iter2.next()); } } return result; } public static void main(String[] args) { List<String> document = Arrays.asList( "Hello world", "This is a test", "Hello world", // duplicate "Another line", "This is a test" // duplicate ); System.out.println("Original document: " + document); // Remove duplicates List<String> uniqueLines = removeDuplicateLines(document); System.out.println("After removing duplicates: " + uniqueLines); // Highlight text List<String> highlighted = highlightText(new ArrayList<>(document), "test"); System.out.println("After highlighting 'test': " + highlighted); // Merge documents List<String> doc1 = Arrays.asList("Line 1", "Line 2", "Line 3"); List<String> doc2 = Arrays.asList("Doc2 Line 1", "Doc2 Line 2"); List<String> merged = mergeDocuments(doc1, doc2); System.out.println("Merged documents: " + merged); } } Database Result Processing
import java.util.*; class DatabaseRecord { private final int id; private final String name; private final double value; private boolean processed = false; public DatabaseRecord(int id, String name, double value) { this.id = id; this.name = name; this.value = value; } public int getId() { return id; } public String getName() { return name; } public double getValue() { return value; } public boolean isProcessed() { return processed; } public void markProcessed() { this.processed = true; } @Override public String toString() { return String.format("Record{id=%d, name='%s', value=%.2f, processed=%s}", id, name, value, processed); } } public class DatabaseResultProcessing { // Process records in batches public static void processInBatches(List<DatabaseRecord> records, int batchSize) { ListIterator<DatabaseRecord> iterator = records.listIterator(); int batchCount = 0; while (iterator.hasNext()) { System.out.println("Processing batch " + (++batchCount)); for (int i = 0; i < batchSize && iterator.hasNext(); i++) { DatabaseRecord record = iterator.next(); processRecord(record); iterator.set(record); // Update the record } // Can go back to review previous records if needed if (iterator.hasPrevious()) { DatabaseRecord previous = iterator.previous(); System.out.println("Last processed in batch: " + previous); iterator.next(); // Move forward again } } } // Filter and transform records public static List<DatabaseRecord> filterAndTransform(List<DatabaseRecord> records) { List<DatabaseRecord> result = new ArrayList<>(); ListIterator<DatabaseRecord> iterator = records.listIterator(); while (iterator.hasNext()) { DatabaseRecord record = iterator.next(); if (record.getValue() > 50.0) { // Filter condition DatabaseRecord transformed = transformRecord(record); result.add(transformed); // Mark original as processed record.markProcessed(); iterator.set(record); } } return result; } // Find records needing reprocessing public static List<DatabaseRecord> findRecordsNeedingReprocessing(List<DatabaseRecord> records) { List<DatabaseRecord> needingReprocessing = new ArrayList<>(); Iterator<DatabaseRecord> iterator = records.iterator(); while (iterator.hasNext()) { DatabaseRecord record = iterator.next(); if (!record.isProcessed() || record.getValue() < 0) { needingReprocessing.add(record); } } return needingReprocessing; } private static void processRecord(DatabaseRecord record) { // Simulate processing record.markProcessed(); System.out.println("Processed: " + record.getName()); } private static DatabaseRecord transformRecord(DatabaseRecord record) { // Simulate transformation return new DatabaseRecord( record.getId(), record.getName().toUpperCase(), record.getValue() * 1.1 ); } public static void main(String[] args) { List<DatabaseRecord> records = Arrays.asList( new DatabaseRecord(1, "Record A", 25.0), new DatabaseRecord(2, "Record B", 75.0), new DatabaseRecord(3, "Record C", 150.0), new DatabaseRecord(4, "Record D", 30.0), new DatabaseRecord(5, "Record E", 200.0) ); System.out.println("=== Database Record Processing ==="); // Process in batches System.out.println("\n1. Processing in batches:"); processInBatches(new ArrayList<>(records), 2); // Filter and transform System.out.println("\n2. Filtering and transforming:"); List<DatabaseRecord> filtered = filterAndTransform(new ArrayList<>(records)); System.out.println("Filtered records: " + filtered); // Find records needing reprocessing System.out.println("\n3. Finding records needing reprocessing:"); List<DatabaseRecord> needingReprocessing = findRecordsNeedingReprocessing(records); System.out.println("Needing reprocessing: " + needingReprocessing); } } Summary
Key Takeaways:
- Iterator provides forward-only traversal with remove capability
- ListIterator extends Iterator with bidirectional traversal and additional operations
- Fail-Fast iterators throw ConcurrentModificationException on structural changes
- Fail-Safe iterators work on collection copies and don't throw exceptions
- Best Practices:
- Always use
hasNext()beforenext() - Use iterator's
remove()method for safe deletion - Choose the right iterator for your needs
- Avoid concurrent modifications
When to Use:
- Iterator: Simple forward traversal, removal needed
- ListIterator: Bidirectional traversal, modification during iteration
- for-each: Simple read-only traversal
Iterators are fundamental to Java collections and provide a robust, standardized way to traverse and manipulate collections safely.