An iterator in Java is an object that enables you to traverse a collection, such as a list, set, or map, without exposing the underlying representation of the collection. This is part of the Java Collections Framework and provides a uniform way to access elements from different types of collections.
An iterator is an interface defined in the java.util
package. It provides methods for iterating over a collection, allowing developers to access each element sequentially without needing to understand the internal structure of the collection. The iterator design pattern helps decouple the collection’s implementation from the code that uses it.
The Iterator
interface has three main methods:
boolean hasNext()
: This method returns true
if there are more elements to iterate over in the collection. Otherwise, it returns false
.
E next()
: This method returns the next element in the iteration. If no more elements are available, it throws a NoSuchElementException
.
void remove()
: This method removes the last element returned by the iterators from the underlying collection. It throws an IllegalStateException
if the next()
method has not yet been called, or if the remove()
method has already been called after the last call to next()
.
Java provides several types of iterators, each serving different use cases:
Here’s a simple example using the Iterator
interface with an ArrayList
:
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorExample {
public static void main(String[] args) {
ArrayList fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
Iterator iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
}
}
In this example, we create an ArrayList
of strings representing fruits. We then obtain an iterator for the list and use it to print each fruit. The hasNext()
method checks if there are more elements, and next()
retrieves the next element.
The ListIterator
is a more powerful iterator that allows you to traverse a list in both directions (forward and backward) and modify the list during iteration.
Here’s an example:
import java.util.ArrayList;
import java.util.ListIterator;
public class ListIteratorExample {
public static void main(String[] args) {
ArrayList fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
ListIterator listIterator = fruits.listIterator();
// Forward traversal
while (listIterator.hasNext()) {
String fruit = listIterator.next();
System.out.println("Forward: " + fruit);
}
// Backward traversal
while (listIterator.hasPrevious()) {
String fruit = listIterator.previous();
System.out.println("Backward: " + fruit);
}
}
}
In this example, we first traverse the list of fruits in the forward direction and then in reverse using the hasPrevious()
and previous()
methods.
remove()
MethodThe remove()
method can be used to delete the last element returned by the iterator. Here’s an example of how to use it:
import java.util.ArrayList;
import java.util.Iterator;
public class RemoveExample {
public static void main(String[] args) {
ArrayList fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
Iterator iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
if (fruit.equals("Banana")) {
iterator.remove(); // Remove Banana from the list
}
}
System.out.println(fruits); // Output: [Apple, Cherry]
}
}
Java iterators are typically “fail-fast.” This means that if the collection is modified while iterating (except through the iterator’s own remove()
method), the iterator will throw a ConcurrentModificationException
. Here’s an example:
import java.util.ArrayList;
import java.util.Iterator;
public class FailFastExample {
public static void main(String[] args) {
ArrayList fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
Iterator iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
if (fruit.equals("Banana")) {
fruits.remove(fruit); // Modifying the collection
}
}
}
}
When you run this code, you’ll encounter a ConcurrentModificationException
because the collection was modified while the iterator was being used.
Since Java 5, the enhanced for loop (also known as the “for-each” loop) provides a simpler way to iterate through collections without explicitly using an iterator:
import java.util.ArrayList;
public class EnhancedForLoopExample {
public static void main(String[] args) {
ArrayList fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
This loop automatically creates an iterator and uses it behind the scenes, making it more readable and concise.
You can also create your own iterator by implementing the Iterator
interface. Here’s an example of a custom collection with a custom iterator:
import java.util.Iterator;
class MyCollection implements Iterable {
private String[] items;
private int size;
public MyCollection(String[] items) {
this.items = items;
this.size = items.length;
}
@Override
public Iterator iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator {
private int index = 0;
@Override
public boolean hasNext() {
return index < size;
}
@Override
public String next() {
if (!hasNext()) {
throw new IndexOutOfBoundsException("No more elements");
}
return items[index++];
}
}
}
public class CustomIteratorExample {
public static void main(String[] args) {
String[] fruits = {"Apple", "Banana", "Cherry"};
MyCollection myCollection = new MyCollection(fruits);
for (String fruit : myCollection) {
System.out.println(fruit);
}
}
}
In this example, MyCollection
implements the Iterable
interface, which requires the implementation of the iterator()
method. Inside it, we define a custom iterator class MyIterator
that provides the hasNext()
and next()
methods.