In This Tutorial, we will Learn About Iterators in Java. We will have Detailed Discussion on the Iterator And ListIterator Interfaces in Java:
We explored all about the Java Collection Framework and its various supporting interfaces and classes in one of our previous tutorials.
When you have a collection, then you want to access its elements, add/remove or process the elements. In order to do all this processing through a Java program, you should be able to traverse through the collection that you are using. This is where the iterator comes into the picture.
Table of Contents:
What Is A Java Iterator?
In Java, an Iterator is a construct that is used to traverse or step through the collection.
In order to use an Iterator, you need to get the iterator object using the “iterator()” method of the collection interface. Java Iterator is a collection framework interface and is a part of the “java.util” package. Using Java Iterator you can iterate through the collection of objects.
Java Iterator interface replaces the enumerator that was used earlier to step through some simple collections like vectors.
The major differences between Java Iterator and Enumerator are:
- Considerable improvement in method names.
- You can remove method elements from the collection that is being traversed using an iterator.
In this tutorial, we will discuss the details of the Iterator interface and ListIterator interface that is a bidirectional interface.
Iterator Types
- Enumerator
- Iterator
- ListIterator
An Enumerator is seldom used now. Hence, in our tutorial series, we will focus on Iterator and ListIterator interfaces.
Iterator Interface In Java
The Iterator interface in Java is a part of the Collections framework in ‘java.util’ package and is a cursor that can be used to step through the collection of objects.
The Iterator interface has the following major characteristics:
- The Iterator interface is available from the Java 1.2 collection framework onwards.
- It traverses the collection of objects one by one.
- Popularly known as “Universal Java Cursor” as it works with all collections.
- This interface supports ‘read’ and ‘remove’ operations i.e. you can remove an element during an iteration using the iterator.
General Representation of the Iterator Interface is given below:
Next, let us take a look at the Iterator methods listed above.
Iterator Methods
The Iterator interface supports the following methods:
#1) Next()
Prototype: E next ()
Parameters: no parameters
Return type: E -> element
Description: Returns the next element in the collection.
If the iteration (collection) has no more elements, then it throws NoSuchElementException.
#2) hasNext()
Prototype: boolean hasNext()
Parameters: NIL
Return type: true => there are elements in the collection.
False => no more elements
Description: The function hasNext() checks if there are more elements in the collection that is being accessed using an iterator. If there are no more elements, then you don’t call the next() method. In other words, this function can be used to decide if the next() method is to be called.
#3) remove()
Prototype: void remove()
Parameters: NIL
Return type: NIL
Description: Removes the last element returned by the iterator iterating over the underlying collection. The remove () method can be called only once per next () call.
If the iterator does not support remove operation, then it throws UnSupportedOperationException. It throws IllegalStateException if the next method is not yet called.
#4) forEachRemaining()
Prototype: void forEachRemaining(consumer <? super E> action)
Parameters: action => action to be performed
Return type: void
Description: Performs the specified action on each of the remaining elements of the collection until all the elements are exhausted or the action throws an exception. Exceptions thrown by action are propagated to the caller.
If the action is null, then it raises nullPointerException. This function is a new addition to the Iterator interface in Java 8.
Java Iterator Example
Let us implement a Java program to demonstrate the use of the Iterator interface. The following program creates an ArrayList of flowers. Then it gets an iterator using the iterator () method of the ArrayList. After that, the list is traversed to display each element.
import java.util.*; public class Main { public static void main(String[] args) { List<String> flowers = new ArrayList<String>(); flowers.add("Rose"); flowers.add("Jasmine"); flowers.add("sunflower"); // Get Iterator Iterator<String>flowersIterator = flowers.iterator(); System.out.println("Contents of ArrayList:"); // Traverse elements using iterator while(flowersIterator.hasNext()){ System.out.print(flowersIterator.next() + " "); } } }
Output:
Limitations Of Iterator Interface
- The operation to replace an element or add a new element cannot be performed with this Iterator.
- The iteration proceeds only in one direction i.e. the forward direction.
- Supports only sequential iteration.
- When large volumes of data are to be iterated, then the performance of the Iterator is affected.
Iterator Vs Iterable
Though the interfaces Iterable and Iterator sound similar, they are completely different. A class that implements the Iterable interface acquires the ability to iterate over the class objects that use the iterator interface.
Given below are some of the main differences between these two interfaces that you must be aware of:
Iterable Interface | Iterator Interface |
---|---|
Represents a collection that can be traversed using foreach loop. | Allows to iterate over some other collection. |
The class that implements the iterable interface has to override iterator() method. | hasNext() and next() methods of Iterator interface are to be overridden by class implementing it. |
Does not store the current state. | Stores the current state of iteration. |
An instance of the iterator interface should be produced every time iterator() method is called. | No such contract for iterator interface. |
Moves only in the forward direction. | Moves in the forward direction and subinterfaces like listIterator support bidirectional traversing. |
Does not provide any method to modify the elements during iteration. | Provides the remove method that can remove element when iteration is in progress. |
ListIterator Interface In Java
The interface ListIterator is a subinterface of the iterator interface. It works on list type collections like Linkedlists, array lists, etc. Thus this interface overcomes the shortcomings of the Iterator interface.
The main characteristics of the ListIterator interface include:
- ListIterator interface extends the Iterator interface.
- ListIterator interface supports CRUD operations i.e. Create, Read, Update and Delete.
- Supports iteration in forward as well as backward direction.
- As this interface is bidirectional, the cursor is always positioned between the previous and next elements.
- This interface mainly works for list implementations like ArrayList, LinkedList, etc.
- Available since Java 1.2
The interface ListIterator is represented as shown below:
As already mentioned, the ListIterator interface extends the Iterator interface. Thus apart from supporting all the methods of iterator interface, as depicted above the ListIterator interface also has methods of its own that help it perform CRUD operations as well as bidirectional iteration.
Let us discuss the ListIterator methods in detail.
ListIterator Methods
Note that the Iterator interface methods, next (), hasNext () and remove () work exactly, in the same way, as the ListIterator interface. Hence, we will skip these methods in this section. In addition to the above-mentioned methods, ListIterator has following methods-
Previous()
Prototype: E previous()
Parameters: NIL
Return type:
E- previous element in the list.
–1 – if the iterator is at the beginning of the list.
Description: This function returns the previous element in the list. Once the previous element is returned, the cursor is moved backward to the next element.
hasPrevious()
Prototype: boolean hasPrevious()
Parameters: NIL
Return type: true => iterator has more elements when the list is traversed backward.
Description: This function checks if the ListIterator has more elements in the backward direction.
previousIndex
Prototype: int previousIndex()
Parameters: NIL
Return type:
int – index of the previous element
–1 – if the pointer is at the start of the list.
Description: Returns the index of the previous element that is returned by the previous() call.
nextIndex
Prototype:int nextIndex()
Parameters: NIL
Return type:
int – next index
–1 – if the iterator is at the end of the list.
Description: Returns the next index of the element in the list. This element is returned by a call to next() method.
set()
Prototype: void set(E e)
Parameters:e – element to be replaced
Return type: NIL
Description: Used to replace the last element with the given element e.
add()
Prototype: void add(E e)
Parameters: e – element to be added
Return type: NIL
Description: Adds new elements to the list at a position before that of the next() element.
List Iterator Example
Now, we know what a ListIterator is and what are the various methods supported by it. Let’s go ahead and implement a Java program to demonstrate the ListIterator.
In this program, we have used ArrayList. Then we use the ListIterator methods to traverse the list in the forward as well as backward direction and display the output.
import java.util.*; class Main { public static void main(String args[]) { List<Integer>num_list = new ArrayList<Integer>(); // Add Elements to ArrayList num_list.add(1); num_list.add(3); num_list.add(5); num_list.add(7); num_list.add(9); // Creatinge a ListIterator ListIteratorlist_it = num_list.listIterator(); System.out.println("Output using forward iteration:"); while (list_it.hasNext()) System.out.print(list_it.next()+" ") ; System.out.print("\n\nOutput using backward iteration:\n") ; while (list_it.hasPrevious()) System.out.print(list_it.previous()+" "); } }
Output:
So far we have discussed the interfaces, iterator, and Listiterator, next we will see the various examples of using these interfaces to traverse different collections. But first, let’s look into traversing of simple arrays and then move on to other collections.
Array Iterator
In Java, there are two ways to iterate over array elements. Let’s describe the ways using code examples.
#1) for loop
This is the simplest way of iterating over an array. We use a simple for loop that will increment the index with each iteration and display its contents.
import java.util.*; public class Main { public static void main(String[] args) { int myArray[] = {2,4,6,8,10,12,14}; int num; System.out.println("Array contents using for loop:"); for (int i = 0; i<myArray.length; i++) { // accessing each element of array num = myArray[i]; System.out.print(num + " "); } } }
Output:
The above program displays the contents of the array using for loop.
#2) forEach loop
This is the second way to iterate over arrays. Here we use a specialized for loop or ‘forEach’ loop. Here we loop through the array for each element and then display the contents.
import java.util.*; public class Main { public static void main(String[] args) { int myArray[] = {2,4,6,8,10,12,14}; int num; System.out.println("Array contents using for each loop:"); for (int i :myArray) { // accessing each element of array num = i; System.out.print(num + " "); } } }
Output:
The forEach is more optimized when compared to for loop. It is shorter to type and is faster too.
ArrayList Iterator
In case you want to traverse through an ArrayList collection, you can do so by using the Iterator interface. As iterator is an interface you cannot instantiate it directly. Instead, you can use the ArrayList collection’s iterator () method to get the iterator and then traverse the list.
Iterator iterator();
Example to demonstrate the ArrayList Iterator.
import java.util.*; public class Main { public static void main(String[] args) { ArrayList<String>myList = new ArrayList<String>(); myList.add("Red"); myList.add("Green"); myList.add("Blue"); myList.add("Brown"); myList.add("Pink"); myList.add("Purple"); Iterator<String>list_it = myList.iterator(); System.out.println("Elements in the arrayList:"); while(list_it.hasNext()) System.out.print(list_it.next() + " "); } }
Output:
LinkedList Iterator
Now let us see the functionality of an iterator in case of LinkedList collection.
LinkedList collection supports the listIterator () method that returns the listIterator to traverse through the linked list.
The general format for this function is
ListIterator list_iter = LinkedList.listIterator(int index);
Here, the index is an integer value that specifies the position in the linkedlist collection from where the traversing should start.
Let us understand the list iterator in the linked list with a sample program. We have modified the same array iterator program and changed it to contain a listiterator with the LinkedList.
import java.util.*; public class Main { public static void main(String[] args) { LinkedList<String>myList = new LinkedList<String>(); myList.add("Red"); myList.add("Green"); myList.add("Blue"); myList.add("Brown"); myList.add("Pink"); myList.add("Purple"); ListIterator<String>list_it = myList.listIterator(0); System.out.println("Elements in the LinkedList:"); while(list_it.hasNext()) System.out.print(list_it.next() + " "); } }
Output:
Java Map / Hashmap Iterator
Map or its variations like hashmap, treemap, etc. are not collections. Hence you cannot directly use the iterator method on it. Instead, you should iterate over the key entry values to read the key/value pairs.
Though you can use various methods like forEach, for loop, etc. to iterate over map values, using an iterator to iterate through the key values is the best and efficient method. Additionally, you can also remove entries from the map during iteration using the remove method.
Example of using the Iterator with HashMap.
import java.util.*; class Main { public static void main(String[] arg) { Map<Integer,String>myMap = new HashMap<Integer,String>(); // enter name/url pair myMap.put(1, "India"); myMap.put(2, "Nepal"); myMap.put(3, "Maldives"); myMap.put(4, "SriLanka"); System.out.println("\tSAARC Member Countries\t"); System.out.println("\tKEY" + " " + "\tCOUNTRY" ); // using iterators Iterator<Map.Entry<Integer, String>>map_itr = myMap.entrySet().iterator(); while(map_itr.hasNext()) { Map.Entry<Integer, String>map_entry = map_itr.next(); System.out.println("\t" + map_entry.getKey() + "\t" + map_entry.getValue()); } } }
Output:
In the above program, we have defined a map with integer keys and string type values. Then we define an iterator over the map. Entry and display the key/value pairs.
Java Set Iterator
The iterator () method of Java.util.set is used to get the iterator that returns the elements in the set in random order.
Iterator set_iterator = Set.iterator();
The “set_iterator” iterates over the different elements of the set and returns their values.
In a similar manner, the hash set also contains an iterator function that returns an iterator like a set iterator.
Iterator hashset_iterator = Hash_Set.iterator();
Given below is the programming example to demonstrate the set iterator.
import java.util.*; public class Main { public static void main(String args[]) { HashSet<String>sports_set = new HashSet<String>(); sports_set.add("Hocky"); sports_set.add("Kabaddi"); sports_set.add("Football"); sports_set.add("Badminton"); sports_set.add("Cricket"); System.out.println("Sports HashSet: " + sports_set); // Creating an iterator Iterator hashset_iter = sports_set.iterator(); // Displaying the values after iterating through the set System.out.println("\nSportsSet iterator values:"); while (hashset_iter.hasNext()) { System.out.println(hashset_iter.next()); } } }
Output:
This implementation uses the HashSet iterator and displays individual values by iterating over the HashSet elements.
Iterator vs ListIterator
Let’s tabularize the main differences between Iterator and ListIterator interfaces.
Iterator | ListIterator |
---|---|
Can traverse all the collections including set, map, etc. | It can be used to traverse only list type collection like ArrayList, LinkedList. |
Iterates the collection only in the forward direction. | Can iterate over the collection in forward as well as backward direction. |
Cannot obtain indexes. | Can obtain indexes. |
No way to add new elements to the collection. | You can add new elements to the collection. |
Iterator cannot modify the elements during iteration. | ListIterator can modify the elements in the collection using the set() method. |
Frequently Asked Questions
Q #1) What is the Iteration in Java?
Answer: An iteration is a process by which a code block is repeatedly executed until a given condition holds or doesn’t exist. Using iteration you can traverse through a sequence of elements or process the data.
Q #2) How many types of Iterators are there in Java?
Answer: Iterators are used to traverse through the collections in Java.
There are three types of iterators in Java:
- Enumerators
- Iterators
- ListIterators
Q #3) How do I use an Iterator in Java?
Answer: In order to use the iterator to traverse through the collection, first, you have to get the iterator using the iterator() method of the specified collection.
Then you can use the hasNext() and next() methods of the iterator to get the element.
Q #4) Why Iterator is used instead of for loop?
Answer: Both the iterator as well as for loop is used to repeatedly execute a specific code block. But the main difference is that in for loop you cannot alter or modify the contents of the collection. Even if you attempt to modify it, it will throw concurrentModificationException. Using iterator you can remove an element from the collection.
Q #5) Why do we need Iterator in Java?
Answer: Iterator helps you to retrieve the elements in the collection or a container without the programmer having to know the internal structure or working of the collection. They are more elegant, consume less memory and also the programmer is spared of in writing lengthy code.
Secondly, the elements can be stored in the collection in any fashion but using an iterator, the programmer can retrieve them just like a list or any other sequence.
Conclusion
We have discussed the iterators in Java that are used with collections in this tutorial. This knowledge of iterators will help the readers to grasp the collections that we are going to learn in our subsequent tutorials.