Java Collection (3) - ListIterator Interface Source & Identification of ListIterator Interface and Iterator Interface

Keywords: Oracle Java

ListIterator interface

Official Document Description:

An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration, and obtain the iterator's current position in the list. A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next(). An iterator for a list of length n has n+1 possible cursor positions, as illustrated by the carets (^) below:

Iterators that allow developers to traverse collections in any direction can modify lists during the iteration process or obtain the current location of iterators. A ListIterator does not have the current element, and its cursor position is always between the two elements. These two elements can be returned by the previous() method and the next(). The set of length n has n+1 possible cursor positions.

Member Method in ListIterator Interface

package java.util;

public interface ListIterator<E> extends Iterator<E> {
    // Query Operations
    boolean hasNext();

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    // Modification Operations

    void remove();

    void set(E e);

    void add(E e);
}

ListIterator is a more powerful Iterator subinterface, which can only be accessed by subclasses of various List interfaces. Because ListIterator does not implement classes, there is only a listIterator() method with a return value type of ListIterator in the List interface. AbstractList, as a direct subclass of List, implements the listIterator() method.

Implementing the Iterator interface in AbstractList uses a method, an internal class. Two methods, two internal classes, are used to implement the ListIterator interface.

Implementation of Iterator Interface Source Code Parsing in AbstractList Abstract Class

A public Iterator < E > iterator () method and a private class Itr implements Iterator < E > class are used.

Public Iterator < E > iterator () method source code

    public Iterator<E> iterator() {
        return new Itr();
    }

It can be seen that in this method only the object of the Itr class is created, so the main implementation process also depends on the Itr class.

Private class Itr implements Iterator < E > class source code

This class contains three member variables and four methods that need to implement the Ietrator interface. (This section deals with the fail-fast mechanism, also known as the Concurrent ModificationException exception)

    protected transient int modCount = 0;
    private class Itr implements Iterator<E> {

        int cursor = 0;    //Cursor position, initial set to 0
        int lastRet = -1;  //The previous position of the current cursor position is initially set to -1
        int expectedModCount = modCount;  //The ModCount value in the cursor throws an exception if it is different from the ModCount value in the collection!

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

Source code parsing of ListIterator interface in AbstractList abstract class

There are two ways to implement this method, one is parametric and the other is parametric.

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }

    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

As can be seen from the above source code, the listIterator() method without parameters calls the listIterator(fianl int index) method with parameters, but sets the parameter value to 0. The method with parameters first determines whether the Index value conforms to the scope, and if it does, calls the inner class ListItr.

Private class ListItr extends Itr implements ListIterator < E > class source code

    private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public E previous() { //Note: Forward operation is also two steps. The first step is to get the previous element of the cursor. The second step is to assign the current position of the cursor to the next position of the cursor.
            checkForComodification();
            try {
                int i = cursor - 1;
                E previous = get(i); 
                lastRet = cursor = i;
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor-1;
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.set(lastRet, e);//This `set()` method is not specifically implemented in abstract classes. The method body just throws an exception. The specific operation requires the subclass to implement itself.

                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                AbstractList.this.add(i, e);  //This `add()'method is not specifically implemented in the abstract class. The body of the method just throws an exception. The specific operation requires the subclass to implement itself.
                lastRet = -1;
                cursor = i + 1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

It can be seen that this class inherits the internal class Itr just now, and then implements the ListIterator interface, which implements the methods in the interface.

Main differences between Iterator interface and ListIterator interface

  • ListIterator has an add() method to add objects to List, while Iterator cannot add objects.
  • Iterator can only traverse forward, but ListIterator can move bidirectionally, and it can also generate position indexes relative to the first and last elements pointed by the iterator in the list. Most importantly, ListIterator can iterate List backwards
  • ListIterator can use the set() method to replace the last element he visited. But Iterator can only traverse collections, not modify them.

Thank

http://blog.csdn.net/u011240877/article/details/52752589
http://blog.csdn.net/a597926661/article/details/7679765
https://docs.oracle.com/javase/8/docs/api/

Posted by ywickham on Wed, 12 Dec 2018 17:33:06 -0800