In Java, a cursor simply refers to any object that lets you go through elements in a collection one by one. You can think of it like a pointer that moves through a list or set, element by element.
Historically, Java provides three main types of cursors:
- Enumeration: Oldest, read-only, used in legacy classes like Vector
- Iterator: Most widely used, allows reading and safe removal
- ListIterator: Works with Lists, supports both forward and backward movement
Iterator is the most commonly used in modern Java, and that’s exactly what we’ll explore next.
Table of Contents:
What is a Java Iterator?
An Iterator in Java is an object that allows you to traverse through a collection like List
, Set
, or Queue
, one element at a time.
It belongs to java.util
package and is a part of the Java Collections Framework. Unlike older cursors like Enumeration
, an iterator lets you read and remove elements from the collection as well.
Think of it as a remote control for your Java collections. You can move to the next item, check if more items exist, and even remove items. We will discuss all these methods in detail, but first, let’s look at why we use iterators instead of loops in Java to iterate through collections.
Why Use Java Iterators Instead of Loops?
You must be wondering why we are even considering iterators when Java already provides the for
and while
loops.
Here are a few reasons why iterators are often the better choice when working with collections.
1. Collection-Agnostic Traversal
An iterator will work and behave the same way across all collections. A traditional for loop, for example, would not work with Set
or Map
, but an iterator will.
2. Safe Element Removal
With a for
loop, removing elements during an iteration could throw a ConcurrentModificationException.
With an iterator, the remove()
method can safely remove the current element without breaking the loop.
3. Cleaner and More Readable Code
Iterators often result in cleaner code, especially when dealing with complex structures or unknown collection sizes.
Understanding the Iterator Interface in Java
In Java, the Iterator
is a generic interface from the java.util
package. It provides a standard way to traverse elements in a collection, one at a time, without exposing the underlying structure.
The iterator interface in Java is declared as:
public interface Iterator<E>
Here, E
represents the type of elements returned by the iterator.
Where It’s Used
You can get an iterator from most Java collections using the .iterator()
method:
List<String> names = new ArrayList<>();
Iterator<String> it = names.iterator();
Once you have the iterator, you can use its methods to loop through the collection safely and efficiently.
Core Methods of the Iterator Interface in Java
The iterator interface in Java provides three main methods that let you loop through a collection safely and efficiently.
1. hasNext()
Checks if the collection has more elements to iterate over.
if (iterator.hasNext()) {
// true if another element exists
}
2. next()
Returns the next element in the collection and moves the cursor forward.
String name = iterator.next();
3. remove()
Removes the last element returned by next()
from the underlying collection.
iterator.remove();
Summary Table
Method | Purpose |
hasNext() | Checks if more elements exist |
next() | Returns the next element |
remove() | Removes the last returned element |
How to Get a Java Iterator
In Java, you don’t need to build an iterator from scratch; you can simply get it from an existing collection using the iterator()
method. It is available on all major collections, including List
, Set
, and even on entryset()
of a Map
. Once you have the iterator, you can safely use it to traverse the collection, one element at a time.
Let’s walk through how it works for different types of collections.
1. Getting a Java List iterator
The List interface is used to have ordered collections that allow duplicates. Let’s see how we can get an iterator from it.
Output:
The .iterator()
method gives us an Iterator<String>
object, and we use a while
loop to print each name using next()
with the condition being that hasNext()
returns true.
2. Getting a Set iterator in Java
Output:
* Output may vary because Set
is not ordered.
- Since
Set
doesn’t support indexing (like get(i)
), using a Set iterator in Java is the most practical way to access its elements.
- We use
hasNext()
and next()
just like before.
3. Iterating Over a Map Using entrySet()
Output:
Map
does not have a direct iterator, but its entrySet()
method returns a Set
of key-value pairs (Map.Entry
objects).
- We get an iterator from this set and use it to print each key (subject) and its corresponding value (score).
entry.getKey()
gives the key; entry.getValue()
gives the value.
Types of Iterators in Java
In Java, any object that allows you to traverse through a collection one element at a time is called a “cursor”. There are three main types of cursors. Let’s have a look at them in detail.
1. Enumeration (Legacy)
- Introduced in Java 1.0
- Can only read elements
Output:
2. Iterator (Modern Standard)
- Introduced in Java 1.2
- Part of the Collection Framework
- Allows reading and safe removal of elements
- Works with all major collections like
List
, Set
, Queue
You’ve already seen this in previous sections. It’s the most common cursor used today.
3. ListIterator (Bi-directional)
- An advanced version of Iterator
- Works only with List implementations like
ArrayList
or LinkedList
- Can traverse forward and backward
- Also supports element modification
Output:
ListIterator
allows both forward and backward traversal.
- It only works on lists and gives more control than a regular
Iterator
.
4. Summary Table
Cursor Type | Direction | Modify Collection | Collection Types | Introduced |
Enumeration | Forward | No | Legacy (Vector) | Java 1.0 |
Iterator | Forward | Remove Only | List, Set, Queue | Java 1.2 |
ListIterator | Both | Add, Remove, Set | List only | Java 1.2 |
ListIterator in Java: Going Forward and Backward
Think of the ListIterator
as a more powerful version of the regular Iterator. It is a part of the java.util package, and is specifically designed for lists.
The difference between ListIterator
and Iterator
In Java is that it allows you to:
- Move both forward and backward
- Add, remove, or update elements while iterating
- Access the index of elements during iteration
How to Get a ListIterator
You get a ListIterator
by calling the .listIterator()
method on a List
object:
ListIterator iterator = list.listIterator();
Forward and Backward Traversal with ListIterator
Output:
.hasNext()
and .next()
move the cursor forward through the list.
.hasPrevious()
and .previous() move it backward.
- This makes
ListIterator
ideal when you need more flexible navigation.
Other Useful Methods in ListIterator in Java
Method | What it Does |
hasNext() | Checks if there’s another element forward |
hasPrevious() | Checks if there’s another element backward |
next() | Returns the next element |
previous() | Returns the previous element |
add(E element) | Adds an element at the current position |
set(E element) | Replaces the last element returned |
remove() | Removes the last element returned |
Difference Between Enumeration, Iterator, and ListIterator
Java gives you the ability to traverse through collections in multiple ways. Each one has a distinct purpose, and learning the difference between them will help you make a better choice in your own implementation.
Feature | Enumeration | Iterator | ListIterator |
Package | java.util | java.util | java.util |
Collection Support | Legacy (Vector) | All collections | Only for Lists |
Direction | Forward only | Forward only | Both forward and backward |
Read Elements | Yes | Yes | Yes |
Remove Elements | No | Yes (remove()) | Yes (remove()) |
Add/Update Elements | No | No | Yes (add(), set()) |
Index Awareness | No | No | Yes (nextIndex(), etc.) |
Fail-Fast vs Fail-Safe Iterators
1. Fail-Fast Iterators
Fail-Fast iterators are designed to immediately throw a ConcurrentModificationException
if the collection is modified in any way after the iterator is created. Except when using its own remove() method.
Most iterators in the Java Collection Framework are fail-fast, including:
ArrayList
HashSet
HashMap
(via entrySet()
, keySet()
, etc.)
2. Fail-Safe Iterators
Fail-safe iterators, on the other hand, work with a duplicate or clone of the collection. So, even if the original collection is modified during iteration, it will not affect the iterator or throw an error in any way.
Fail-safe iterators are used in concurrent collections, such as
- CopyOnWriteArrayList
- ConcurrentHashMap
A rule of thumb that you can keep in mind is: Use fail-safe collections when working with multiple threads or if the collection needs to be modified during iteration.
Concept + examples
Common interview question
Advantages and Limitations of Java Iterators
Iterators are simple, powerful, and widely supported tools in Java, but like everything, they come with their own pros and cons.
Aspect | Advantages | Limitations |
Collection Compatibility | Works uniformly with List , Set , Queue , etc. | Not usable with Map directly (requires entrySet() workaround) |
Traversal Direction | Simple forward traversal using hasNext() and next() | Only supports forward direction (use ListIterator for both ways) |
Modification Support | Allows safe removal of elements via remove() | Cannot add or update elements (use ListIterator instead) |
Index-Free Looping | Clean syntax without dealing with indices | No access to the element’s position or index |
Generics Support | Fully generic — no need for casting | NA |
Thread Safety | NA | Not thread-safe; requires synchronization or concurrent collections
|
Common Mistakes to Avoid with Java Iterators
Iterators can be a difficult topic for beginners, especially when trying to implement them in your own code. Keep a lookout for these common mistakes that you should avoid when implementing iterators in Java.
- Modifying the Collection While Iterating
The above code will throw a ConcurrentModificationException
because we are removing the value from the collection directly.
Fix:
Use Iterator.remove()
instead of modifying the collection directly.
- Calling remove() Without next()
You must call next()
before remove()
, otherwise, the iterator doesn’t know which element to delete.
Fix:
You must call next()
before calling remove()
.
- Trying to Iterate a Map Directly
Map
doesn’t implement Iterable, so you can’t get an iterator from it directly.
Fix:
Use entrySet()
like so:
Iterator<Map.Entry> it = scores.entrySet().iterator();
- Using ListIterator on a Non-List Collection
Set does not support ListIterator
; it’s only available for List
types.
Fix:
Use a regular iterator.
Iterator it = set.iterator();
Conclusion
So far in this blog, we have covered what iterators are in Java, each type, and their implementation in detail. If you are looking to dive deeper into Java topics such as Object-Oriented Programming or exception handling, check out our Java certification course.
Or if you are preparing for your first Java technical interview, our Java interview questions and answers can help you get started.
Java Iterator- FAQs
1. Can I use a Java iterator with a Map?
Yes, but not directly. Since
Map
stores data in key-value pairs, you need to iterate over its entrySet()
, keySet()
, or values()
like this:
Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();
2. What happens if I modify a collection while iterating?
If you modify the collection directly (using remove()
on the list), you’ll get a ConcurrentModificationException
.
Instead, you can use it iterator.remove()
for safe removal during iteration.
3. What is the difference between Iterator and ListIterator?
– Iterator
supports only forward traversal and element removal.
– ListIterator
supports forward and backward traversal and can also add or replace elements during iteration.
– Also, ListIterator
only works with List
types like ArrayList
.
4. Can I reset a Java iterator?
No, you cannot reset an iterator once it has reached the end of a collection. But you can always create a new iterator to start over.
5. Are iterators thread-safe?
No. Iterators
Standard collections like ArrayList
or HashSet
are not thread-safe. For concurrent use, consider CopyOnWriteArrayList
or ConcurrentHashMap
, which provides fail-safe iterators.