Java Collections Traversing | Set 1 - Walking Techie

Blog about Java programming, Design Pattern, and Data Structure.

Tuesday, August 9, 2016

Java Collections Traversing | Set 1

In Java Collections Framework, different kind of collections store their elements using different data structure. Java provide different ways to traverse on collections objects.

  • Using Iterator
  • Using ListIterator
  • Using Enumeration
  • Using for-each loop
  • Using forEach() method

1.Using Iterator

A collection provides an iterator to iterate over all its elements. Iterator is an interface and found in java.util package. Iterator<E> interface has following methods:

  • boolean hasNext(): Check if there is an element that has not been processed yet.
  • E next(): Access the next element in the collection.
  • default void remove(): Remove the last access element in the collection.
  • default void forEachRemaining(Consumer action): Performs the given action for each remaining element until all elements have been processed or the action throws an exception.

An iterator in java is an instance of Interface<E> interface.

We can get an iterator for collection using iterator() method of Collection interface.

Example 1

The following code create an list of Strings and get iterator for the list:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorDemo {

 public static void main(String[] args) {
  List<String> list = new ArrayList<String>();
  list.add("John");
  list.add("Michel");
  list.add("Sachin");

  // get an iterator for the list
  Iterator<String> nameIterator = list.iterator();

  // iterate over all the element of the list
  while (nameIterator.hasNext()) {
   // get the next element from the list
   String name = nameIterator.next();
   System.out.println(name);
  }
 }
}

The hasNext() method returns true if the iteration has more elements in collection to iterate. otherwise, it returns false.

The next() method returns the next element from the collection. We should always call hasNext() method before calling next() method. The next() method throws NoSuchElementException if the iteration has no more elements.

The remove() method removes the last element that was returned by last time by the next() method. This method can be called only once for every call to the next() method.

If the renove() method is called more than once for each next() or before the call of next(), it throws java.lang.IllegalStateException.

The default implementation throws an instance of UnsupportedOperationException and performs no other action. The UnsupportedOperationException throws if the operation is not supported by this iterator.

Click here to see how remove() method removes the element from the collection and you can also understand, scenario in which ConcurrentModificationException throws while iterating over collection.

Example 2

The forEachRemaining() perform the action on every element of the collection that has not been processed yet. Actions are performed in the order of iteration, if that order is specified.

The action to be performed for each element, throws NullPointerException if the specified action is null. The action is specified as Consumer.

Below code is default implementation of forEachRemaining() method available under java Iterator interface.It is java 8 feature.

default void forEachRemaining(Consumer action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }

The following code create an list of Strings and get iterator for the list:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorDemo {

 public static void main(String[] args) {
  List<String> list = new ArrayList<String>();
  list.add("John");
  list.add("Michel");
  list.add("Sachin");

  // get an iterator for the list
  Iterator<String> nameIterator = list.iterator();
  // it will print out the element of collection
  nameIterator.forEachRemaining(n -> {
   System.out.println(n);
  });
 }
}

Output of example 1 and example 2 program is shown below:

John
Michel
Sachin

2.Using ListIterator

The ListIterator allows programmer to traverse the list in either direction, modify the list during iteration, and obtain the iterator's current position in the list.

The ListIterator is an interface and found in java.util package.

The ListIterator<E> interface has following method:

  • boolean hasNext(): Check if there is an element that has not been processed yet in forward direction.
  • E next(): Access the next element in the collection and advance the cursor position.
  • boolean hasPrevious(): Returns true if this list iterator has more elements when traversing the list in the reverse direction.
  • E previous(): Returns the previous element in the list and moves the cursor position backwards.
  • int nextIndex(): Return the index of the element that would be returned by a subsequent call to next, or list size if the list iterator is at the end of the list.
  • int previousIndex(): Return the index of the element that would be returned by a subsequent call to previous, or -1 if the list iterator is at the beginning of the list.
  • void remove(): Removes the last element from the list that was returned by next or previous. This call can only be made once for every call to next or previous.
  • void set(E e): Replaces the last element returned by next or previous with the specified element. This call can be made only if neither remove nor add have been called after the last call to next or previous.
  • void add(E e): Inserts the specified element into the list. The element is inserted immediately after the recently returned element in the traversing direction. If the list contains no elements, the new element becomes the sole element on the list.

Example 3

Below example explains the methods of ListIterator interface.

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorDemo {

 public static void main(String[] args) {
  List<String> name = new ArrayList<String>();
  name.add("Santosh");
  name.add("Kumar");
  ListIterator<String> nameIterator = name.listIterator();
  System.out
  .println("List traversal in forward direction using ListIterator...");
  while (nameIterator.hasNext()) {
   System.out.println(nameIterator.next());
  }
  System.out.println("---------------------------------------");
  System.out
  .println("List traversal in backward direction using ListIterator...");
  while (nameIterator.hasPrevious()) {
   System.out.println(nameIterator.previous());
  }
  System.out.println("---------------------------------------");

  // creating empty list to show set and add method of ListIterator
  // interface
  List<String> list = new ArrayList<String>();

  System.out.println(list);
  ListIterator<String> iterator = list.listIterator();

  // Explains about add(E e) method.
  iterator.add("Messi");
  // display [Messi]
  System.out.println(list);
  /*
   * The new element is inserted before the implicit cursor , so
   * subsequent call to next or hasNext would be unaffected.
   */
  if (iterator.hasNext())
   System.out.println("Last next method called and returned element: "
     + iterator.next());
  /*
   * if you subsequent call to previous would return the new element, and
   * hasPrevious() method return true.
   */
  if (iterator.hasPrevious())
   System.out
   .println("Last previous method called and returned element: "
       + iterator.previous());

  // Explains about Set(E e) method.

  /*
   * Set(e) replace the last element returned by the previous with the new
   * element. In this example "Ronaldo" will replace "Massi"
   */
  iterator.set("Ronaldo");
  System.out.println(list);

  /*
   * set method call can be made only if neither remove nor add have been called after
   * the last call to next or previous
   */

  if (iterator.hasNext())
   System.out.println("Last next method called and returned element: "
     + iterator.next());

  iterator.add("Xavi");

  System.out.println(list);
  iterator.set(" Aguero");// this will throws IllegalStateException
 }
}

Output of above program is shown below:

List traversal in forward direction using ListIterator...
Santosh
Kumar
---------------------------------------
List traversal in backward direction using ListIterator...
Kumar
Santosh
---------------------------------------
[]
[Messi]
Last previous method called and returned element: Messi
[Ronaldo]
Last next method called and returned element: Ronaldo
[Ronaldo, Xavi]
Exception in thread "main" java.lang.IllegalStateException
 at java.util.ArrayList$ListItr.set(ArrayList.java:941)
 at com.walkingtechie.iterator.ListIteratorDemo.main(ListIteratorDemo.java:75)

Difference between Iterator and ListIterator interface.

Iterator ListIterator
Iterator can be used in List, Set and Queue. ListIterator can be used in List only.
Iterator can traverse in forward direction only. ListIterator can traverse both forward and backward direction.
Set and Add both operations are not allowed in Iterator. Set and Add both operations are allowed in ListIterator.
Iterator's current position during traversal can not be determined using Iterator. ListIterator can obtain the iterator's current position in the list.
We can not obtain the index using Iterator as there is no such methods present. ListIterator can obtain the index of the elements using previousIndex(E e) or nextIndex(E e) methods.

No comments :

Post a Comment