Cursors in java

Purpose of Cursor in Collections:

If we want to get objects one by one from the Collection then, we should go for Cursor. There are four types of Cursors available in java:

Note: Spliterator is introduced in java 8 so I’ll discuss about it in some other post when I’ll be brushing up my skills on java 8 feature.

Enumeration

public Enumeration elements();
// e.g.
Enumeration e = v.elements(); // where v is some legacy Collection object
Methods of Enumeration
public boolean hasMoreElements(); // checks whether more elements are present in the Collection.
public Object nextElement(); // Returns the next element

Implementation Demo:

Vector v = new Vector();
for(int i = 0; i < 11; i++){
    v.addElement(i);
    }
    System.out.println(v);
    Enumeration e = v.elements();
    while(e.hasMoreElements()){
        Integer i = (Integer) e.nextElement();
        if(i % 2 == 0)
            System.out.print(i + " ");
    }

Limitations of Enumeration

  1. We can apply Enumeration concept only for legacy classes therefore, Enumeration is not a universal Cursor.
  2. By using Enumeration, we can get only read access but we cannot perform remove operation.

To overcome above limitations, we should go for Iterator.

Iterator

  1. We can apply Iterator concept for any Collection object and hence it is universal Cursor.
  2. By using Iterator, we can perform both read and remove operations.
  3. We can create Iterator object by using iterator() method of Collection interface.
public Iterator iterator();
e.g.
Iterator itr = c.iterator(); // where c is any Collection object.

Methods of Iterator

public boolean hasNext();
public Object next();
public void remove();

Note: You can see the methods for any Classes or interface using the command javap java.util.Iterator.

Implementation Demo

List al = new ArrayList(); // To remove warning use Generics
        for(int i = 0; i < 11; i++)
            al.add(i);
        Iterator itr = al.iterator();
        while(itr.hasNext()){
            Integer i = (Integer) itr.next();
            if(i % 2 != 0) // Remove all the odd numbers from ArrayList al
                itr.remove();
        }
        System.out.println(al); // [0, 2, 4, 6, 8, 10]
    }

Limitations of Iterator

  1. By using Enumeration and Iterator, we can always iterate only in forward direction and we cannot iterate the Collection object in backward direction. These are single direction Cursors.
  2. By using Iterator, we can perform only read and remove operations and we cannot perform replacement and addition of new objects.

To overcome above limitations, we should go for ListIterator.

ListIterator

  1. ListIterator is the child interface of Iterator and hence all methods present in Iterator are available to the ListIterator by default.
  2. By using ListIterator, we can iterate the Collection objects either in forward or backward direction and hence it is bi-directional cursor.
  3. By using ListIterator, we can perform replacement and addition of new objects in addition to read and remove operations.
  4. We can create ListIterator by using listIterator() method of List interface.
public ListIterator listIterator();
// e.g.
ListIterator ltr = l.listIterator(); // where l is any List object.

Methods of ListIterator

ListIterator defines the following 9 methods:

// The below three methods are meant for forward iteration
public boolean hasNext();
public Object next();
public int nextIndex();
// The below three methods are meant for backward iteration
public boolean hasPrevious();
public Object previous();
public int previousIndex();
// Extra operations
public void remove();
public void add(Object o);
public void set(Object o);

Note: You can see the methods for any Classes or interface using the command javap java.util.ListIterator.

Implementation Demo

LinkedList ll = new LinkedList();
ll.add("Mandy8055");
ll.add("David");
ll.add("Nag");
ll.add("Saurabh");
System.out.println(ll);
ListIterator ltr = ll.listIterator();
while(ltr.hasNext()){
    String s = ltr.next().toString();
    if(s.equals("Mandy8055"))
        ltr.remove();
    else if(s.equals("Saurabh"))
        ltr.add("Lipika");
    else if(s.equals("Nag"))
        ltr.set("Shweta");
    }
System.out.println(ll); // [David, Shweta, Saurabh, Lipika]

The most powerful Cursor is ListIterator but its limitation is it is applicable only for List interface.

Comparison(gist) between 3 Cursors:

Properties Enumeration Iterator ListIterator
1. where we can apply. Only for legacy classes. Applicable for any Collection classes. Applicable only for List Objects.
2. Is it legacy? Yes NO NO
3. Iteration Direction Forward direction Forward direction Bi-directional i.e. forward and backward.
4. Allowed operations Only read operation Read and remove operation. Read, remove, add and replace operation.
5. Method to get the Cursor Using elements() method of Vector class. Using iterator method of Collection interface. Using ListIterator of List interface.
6. Important Methods 2 Methods 3 methods 9 methods

Internal Implementation of Cursors:

This is one of the most disturbing topic which I came through when I was preparing for my java certification. I was thinking every time we want to define a Cursor on some Collection object, I would create an object like Enumeration e or Iterator itr, etc. but then I realized how can we even think of creating an object for Interface:dizzy_face: since, Enumeration, Iterator and ListIterator are Interfaces.

Finally, I got the solution of this problem by running the below program.

Vector v = new Vector();
Enumeration e = v.elements();
System.out.println(e.getClass().getName());
Iterator itr = v.iterator();
System.out.println(itr.getClass().getName());
ListIterator ltr = v.listIterator();
System.out.println(ltr.getClass().getName());