The 3 CURSORS OF JAVA:
We use cursors when we want to get objects from a Collection one by one. There are 3 cursors in JAVA :
- Enumeration
- Iterator
- ListIterator
Let’s discuss these cursors one by one :
Enumeration in Java
We can use Enumeration to get objects one by one from legacy collection object. To create Enumeration object we have to use ‘elements()’ method of Vector Class (i.e. public enumeration elements()).
As example, let ‘v’ is a vector object which contains [0,1,2,3,4,5,6] these elements.
Now if we print ‘v’ by System.out.println(v) then it will print the whole vector object, but if we have to deal with every single element of this vector object then what we will do is we will use enumeration as :
Enumeration e = v.elements();
Methods in Enumeration:
Enumeration contains only two methods:
- boolean hasMoreElements() : We use this method to check if there are more elements present in the enumeration object for processing or not. If more elements are there this method will return ‘True’ and ‘False’ otherwise.
- public Object nextElement() : If more elements are there we use this method to get the next object ready for processing. This method will return the next Object.
Let’s discuss Enumeration with a small program :
import java.util.*; class EnumDemo { public static void main(String[] args) { Vector vek = new Vector(); // Creates a new blank vector for(int i=0;i<10;i++) { vek.addElement(i); } // vek = [0,1,2,3,4,5,6,7,8,9] System.out.println(vek); // Output : [0,1,2,3,4,5,6,7,8,9] Enumeration enu = vek.elements(); // An enumeration objects created corresponding to vector object vek while(enu.hasMoreElements()) { Integer in = (Integer)enu.nextElement(); // As ‘enu’ will return enumeration object so typecasting to integer required if(in%2==0) System.out.println(in); //Even numbers will be printed and odd numbers will be ignored } System.out.println(vek); // Output : [0,1,2,3,4,5,6,7,8,9] } }
When we compile this code, the code will compile successfully but will give the following warnings due to generics :
Note: EnumDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Now if we run the code, the following output will be produced :
Output :-
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 0 2 4 6 8 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Now, if we can solve all requirements of cursors with Enumerations then, why there is 3 cursors? Obviously if there is some more cursors so there must be some limitations in Enumeration.
Limitations of Enumeration:
- Enumeration cursor was introduced in JAVA version 1.0 (In this version Vector was also introduced). So Enumeration is applicable only for legacy classes, it is not a universal cursor. That means, we can use Enumeration for Vector, Stack etc. but not in case of ArrayList or LinkedList.
- In Enumeration there is only two methods, one is for checking whether there is more elements or not and the second is for if there is more element then to pass element one by one. But to remove elements from the Collection there is no method. That means we get only read access through Enumeration.
To overcome these limitations, we need a higher level cursor, which is nothing but Iterator.
Iterator in Java
- Unlike Enumeration, Iterator is applicable to all Collection (Interface), that means Iterator is a Universal Cursor.
- In Enumeration, we get only read access over objects, we couldn’t remove objects. But in case of Iterator, we can both read and remove objects.
Now to create iterator object there was a method in Collection (Interface) that is public iterator() which returns Iterator object.
As example, say c is any Collection (LinkedList, ArrayList, Vector, Stack) object, then we can write :
Iterator it = c.iterator()
Methods of Iterator:
- public boolean hasNext() : This method is used to check if there are more elements present in the Iterator object for processing or not. If more elements are there this method will return ‘True’ and ‘False’ otherwise.
- public Object next() : If more elements are there we use this method to get the next object ready for processing. This method will return the next Object.
- public void remove() : This method is used to remove object from the Collection.
Let’s understand Iterator with an example :
import java.util.*; class IterDemo { public static void main(String[] args) { Vector vek = new Vector(); // Creates a new blank vector for(int i=0;i<10;i++) { vek.addElement(i); } // vek = [0,1,2,3,4,5,6,7,8,9] System.out.println(vek); // Output : [0,1,2,3,4,5,6,7,8,9] Iterator it = vek.iterator(); // An Iterator objects created corresponding to vector object vek while(it.hasNext()) { Integer in = (Integer)it.next(); // As ‘it’ will return Iterator object so typecasting to integer required if(in%2==0) System.out.println(in); //Even numbers will be printed else it.remove(); //Odd numbers will be removed, this remove concept was not //there in Enumeration } System.out.println(vek); // Output : [0,2,4,6,8] // In case of Enumeration, Output was : [0,1,2,3,4,5,6,7,8,9] } }
When we compile this code, the code will compile successfully with the following two warnings due to generics :
Note: IterDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
If we use proper generics then we won’t get any warning.Now if we run our code we will get the following output :
Output : –
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 0 2 4 6 8 [0, 2, 4, 6, 8]
Limitations of Iterator:
There are some limitations of Iterator :
- By using Iterator (even with Enumeration) we can move only toward forward direction, we can’t move towards backward direction, as Iterator and Enumeration are single direction cursor, not bidirectional cursor.
- By using Iterator only read and remove operations, but we can’t perform replacement or addition of new objects.
To overcome above limitations we should go for a higher level Iterator i.e. ListIterator.
List Iterator in Java:
ListIterator is the child interface of Iterator. These are the features of ListIterators:
- ListIterator is a bidirectional cursor, which means we can move both in forward and reverse (backward) direction.
- By using ListIterator we can perform addition, removal, and replacement operations on elements in a Collection.
Now to create ListIterator object there was a method in List (Interface) that is public listIterator() which returns ListIterator object.
As example, say l is any List (LinkedList, ArrayList) object, then we can write :
ListIterator lt = l.listIterator();
Methods in ListIterator
As ListIterator is the child Interface of Iterator Interface so all methods of Iterator are readily available to ListIterator. ListIterator defines the following 9 methods :
These 3 methods are meant for forward movement.
- public boolean hasNext() : This method is from Iterator Interface, used to check if there is any element present in next position or not. If any element present this method will return ‘True’ and ‘False’ otherwise.
- public Object next() : This method is from Iterator Interface, used to get the next object from the List (if there is a next Object). This method will return the object if it is present.
- public int nextIndex() : This method is used to get the index of the next element in the List.
These 3 methods are meant for backward operation.
- public boolean hasPrevious() : This method is defined in ListIterator, used to check if there is any element present in previous position or not. If any element present this method will return ‘True’ and ‘False’ otherwise.
- public Object previous() :This method is defined in ListIterator, used to get the previous object from the List (if there is a next Object). This method will return the object if it is present.
- public int previousIndex() :This method is used to get the index of the previous element in the List.
These 3 methods are extra methods :
- public void remove() : This method is used to remove an object from the List.
- public void add(Object obj) : This method is used to add a specified object in the List.
- public void set(Object obj) : This method is used to replace an element in the List.
Let’s understand ListIterator with an example :
import java.util.*; class LstItrDemo { public static void main(String[] args) { LinkedList ls = new LinkedList(); //This will create a blank LinkedList ls.add(“PADHLE”); // PADHLE will be added ls.add(“RAJESH”); // RAJESH will be added ls.add(“SINHA”); // SINHA will be added ls.add(“BANDEL”); // BANDEL will be added ls.add(“EARTH”); // EARTH will be added System.out.println(ls); // Output : [PADHLE, RAJESH, SINHA, BANDEL, EARTH] ListIterator lstir = ls.listIterator(); // ListIterator object lstir created corresponding to ls LinkedList while(lstir.hasNext()) { String S = (String)lstir.next(); if(S.equals(“EARTH”)) lstir.remove(); // EARTH will be removed from LinkedList else if(S.equals(“BANDEL”)) lstir.set(“BANSBERIA”); //BANDEL will be replaced by BANSBERIA } System.out.println(ls); // Output : [PADHLE, RAJESH, SINHA, BANSBERIA] } }
When we compile this code, the code will compile successfully with the following warnings due to generics :
Note: LstItrDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Now if we run this code, following output will be produced :
Output :
[PADHLE, RAJESH, SINHA, BANDEL, EARTH] [PADHLE, RAJESH, SINHA, BANSBERIA]
The most powerful cursor is ListIterator; but its limitation is, it is applicable only to List Objects.