Static utility methods, classes, and abstract classes for iteration. : Iterator « Collections Data Structure « Java






Static utility methods, classes, and abstract classes for iteration.

       
/*
 * LingPipe v. 3.9
 * Copyright (C) 2003-2010 Alias-i
 *
 * This program is licensed under the Alias-i Royalty Free License
 * Version 1 WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the Alias-i
 * Royalty Free License Version 1 for more details.
 *
 * You should have received a copy of the Alias-i Royalty Free License
 * Version 1 along with this program; if not, visit
 * http://alias-i.com/lingpipe/licenses/lingpipe-license-1.txt or contact
 * Alias-i, Inc. at 181 North 11th Street, Suite 401, Brooklyn, NY 11211,
 * +1 (718) 290-9170.
 */

//package com.aliasi.util;

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


/**
 * Static utility methods, classes, and abstract classes for
 * iteration.
 *
 * @author  Bob Carpenter
 * @author  Mike Ross
 * @version 4.0.0
 * @since   LingPipe2.0
 */
public class Iterators {

    // do not allow instances
    private Iterators() {
        /* no instances */
    }

    static final Iterator<Object> EMPTY_ITERATOR
        = new Empty<Object>();

    /**
     * Returns an iterator that has no elements.  Thus {@code
     * hasNext()} will always return {@code false} and {@code next()}
     * will always throw a {@code NoSuchElementException}.
     *
     * @return The empty iterator.
     */
    public static <E> Iterator<E> empty() {
        @SuppressWarnings("unchecked")
        Iterator<E> emptyIterator = (Iterator<E>) EMPTY_ITERATOR;
        return emptyIterator;
    }

    /**
     * Returns an iterator over the single specified element.
     * Thus {@code next()} will return the specified element
     * on the first call, with subsequent calls
     * throwing a {@code NoSuchElementException}  .
     *
     * @param e The object to return in the iterator.
     * @return The iterator over the specified object.
     */
    public static <E> Iterator<E> singleton(E e) {
        Iterator<E> singletonIterator = new Singleton<E>(e);
        return singletonIterator;
    }

    /**
     * Returns a newly constructed iterator over the specified pair of
     * elements.
     *
     * <p><i>Implementation Note:</i> References to the elemenets are
     * removed from iterator after they are returned through {@code
     * next()}.
     *
     * @param e1 First element returned.
     * @param e2 Second element returned.
     * @return The iterator over the pair of elements specified.
     */
    public static <E> Iterator<E> pair(E e1, E e2) {
        return new Pair<E>(e1,e2);
    }

    /**
     * Returns an iterator constructed from the specified variable
     * length argument list of objects.  
     *
     * <p>Remove is supported, but has no effect on anything as the
     * list from which elements are being deleted is only used for the
     * iterator.
     *
     * @param es Array of objects for iteration.
     * @return Iterator over list.
     */
    public static <E> Iterator<E> list(E... es) {
        return java.util.Arrays.<E>asList(es).iterator();
    }

    /**
     * Returns an unmodifiable view of the specified iterator.
     * Calls to {@code next()} and {@code hasNext()} are delegated
     * to the specified iterator as made.  Calls to {@code remove()}
     * throw unsupported operation exceptions.
     *
     * @param it Iterator to view.
     * @return Unmodifiable view of specified iterator.
     */
    public static <E> Iterator<E> unmodifiable(Iterator<E> it) {
        final Iterator<E> mIt = it;
        return new Iterator<E>() {
            public boolean hasNext() {
                return mIt.hasNext();
            }
            public E next() {
                return mIt.next();
            }
            public void remove() {
                String msg = "Cannot remove from an unmodifiable iterator.";
                throw new UnsupportedOperationException(msg);
            }
        };
    }

    /**
     * Returns an iterator that runs through the first iterator's
     * elements and then runs through the second iterator's elements.
     *
     * <p>References to the iterators are freed after it is finished
     * iterating.
     *
     * @param it1 The first iterator in the sequence.
     * @param it2 The second iterator in the sequence.
     * @return The iterator over the two iterators.
     */
    public static <E> Iterator<E> sequence(Iterator<? extends E> it1,
                                           Iterator<? extends E> it2) {
        Iterator<E> result = new Sequence<E>(it1,it2);
        return result;
    }

    public static <E> Iterator<E> sequence(List<? extends Iterator<? extends E>> iterators) {
        @SuppressWarnings({"unchecked","rawtypes"})
        Iterator<? extends E>[] elts
            = (Iterator<? extends E>[]) iterators.toArray(new Iterator[0]);
        Iterator<E> it = new Sequence<E>(elts);
        return it;
    }

    public static <E> Iterator<E>
        sequence(Iterator<? extends Iterator<? extends E>> iteratorOfIterators) {

        Iterator<E> it = new Sequence<E>(iteratorOfIterators);
        return it;
    }


    /**
     * Returns an iterator over the specified array of objects.
     *
     * <p><i>Warning:</i> The array is not copied, so any changes in
     * the underlying array are reflected in the iterator.
     *
     * <P><I>Implementation Note:</I> this class does not
     * automatically free references in the underlying array, because
     * the array may be used elswhere.  If reference freeing is
     * critical here, a call to {@code remove()} after ever call to
     * {@code next()} will free the references in the array.
     *
     * @param members Array of elements over which to iterate.
     * @return The iterator over the array elements.
     */
    public static <E> Iterator<E> array(E[] members) {
        return new Array<E>(members);
    }

    /**
     * Returns a newly constructed iterator over the specified
     * object array slice.
     *
     * <p>The {@code remove()} method is not supported.
     *
     * <p><i>Warning:</i> The array is not copied, so any changes in
     * the underlying array are reflected in the iterator.
     *
     * <P><I>Implementation Note:</I> this class does not
     * automatically free references in the underlying array, because
     * the array may be used elswhere.
     *
     * @param members Array of objects over which to iterate.
     * @param start Index of first object to return.
     * @param length Number of objects to iterate.
     * @throws Illegal argument exception if {@code start < 0} or
     * {@code start + length > objects.length()}.
     */
    public static <E> Iterator<E> arraySlice(E[] members, int start, int length) {
        return new ArraySlice<E>(members,start,length);
    }

    /**
     * An <code>Iterator.Array</code> iterates over the elements of an
     * array specified at construction time.
     *
     * <P><I>Implementation Note:</I> this class does not automatically
     * free references in the underlying array, because the array
     * may be used elswhere.  If reference freeing is critical here,
     * a call to <code>remove()</code> after ever <code>next()</code>
     * will free the references in the array.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe1.0
     * @param <E> the type of objects returned by the iterator
     */
    static class Array<E> implements Iterator<E> {

        /**
         * Array to iterate over.
         */
        private final E[] mMembers;

        /**
         * Current position of next element to return in array.
         */
        private int mPosition;

        /**
         * Construct an array iterator from the specified array.
         *
         * @param members Array basis of the constructed iterator.
         */
        public Array(E[] members) {
            mMembers = members;
        }

        /**
         * Returns <code>true</code> if this iterator has more
         * elements.
         *
         * @return <code>true</code> if this iterator has more
         * elements.
         */
        public boolean hasNext() {
            return mPosition < mMembers.length;
        }

        /**
         * Returns the next element in the array.
         *
         * @return Next element in the array.
         * @throws NoSuchElementException If there are no more
         * elements left in the array to return.
         */
        public E next() {
            if (!hasNext())
                throw new NoSuchElementException();
            return mMembers[mPosition++];
        }

        /**
         * Sets position in underlying array corresponding to the most
         * recently returned token to <code>null</code>.
         *
         * @throws IllegalStateException If the <code>next</code>
         * method has not been called, or the <code>remove</code>
         * method has already been called after the last call to the
         * next method.
         */
        public void remove() {
            if (mPosition < 1)
                throw new IllegalStateException("Next not yet called.");
            if (mMembers[mPosition-1] == null)
                throw new IllegalStateException("Remove already called.");
            mMembers[mPosition-1] = null;
        }
    }

    /**
     * An <code>Iterators.ArraySlice</code> iterates over a slice of
     * an array specified by start index and length.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe1.0
     * @param <E> the type of objects returned by the iterator
     */
    static class ArraySlice<E> implements Iterator<E> {

        /**
         * The underlying objects represented in this array iterator.
         */
        private final E[] mObjects;

        /**
         * Index of next element to return.
         */
        private int mNext;

        /**
         * Index one past the index of the last element to return.
         */
        private final int mLast;

        /**
         * Construct an iterator over the specified array of objects
         * that begins at the object at the specified start index
         * and carries through to the other objects.
         *
         * @param objects Array of objects over which to iterate.
         * @param start Index of first object to return.
         * @param length Number of objects to iterate.
         * @throws Illegal argument exception if {@code start < 0} or
         * {@code start + length > objects.length}.
         */
        public ArraySlice(E[] objects,
                          int start, int length) {
            if (start < 0) {
                String msg = "Require start of slice to be non-negative."
                    + " Found start=" + start;
                throw new IllegalArgumentException(msg);
            }
            if (start + length > objects.length) {
                String msg = "Start plus length must not exceed array length."
                    + " Found objects.length=" + objects.length
                    + " start=" + start
                    + " length=" + length
                    + " (start+length)=" + (start+length);
                throw new IllegalArgumentException(msg);
            }
            mObjects = objects;
            mNext = start;
            mLast = start + length;
        }

        /**
         * Returns <code>true</code> if there are more objects
         * to return.
         *
         * @return <code>true</code> if this iterator has more
         * elements.
         */
        public boolean hasNext() {
            return mNext < mLast;
        }

        /**
         * Returns the next object for this iterator, throwing
         * an exception if there are no more objects left.
         *
         * @return Next object from this iterator.
         * @throws NoSuchElementException If there are no more
         * elements to return.
         */
        public E next() {
            if (!hasNext()) throw new NoSuchElementException();
            return mObjects[mNext++];
        }

        /**
         * Throws an <code>UnsupportedOperationException</code>.
         *
         * @throws UnsupportedOperationException If called.
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * An <code>Iterator.Empty</code> is an iterator with no
     * objects.  The method {@link #hasNext()} always returns
     * <code>false</code>, while the methods {@link #next()}
     * and {@link #remove()} always throw exceptions.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe3.0
     * @param <E> the type of objects returned by the iterator
     */
    static class Empty<E> implements Iterator<E> {

        /**
         * Construct an empty iterator.
         */
        public Empty() {
            /* do nothing */
        }

        /**
         * Always returns <code>false</code>.
         *
         * @return <code>false</code>.
         */
        public boolean hasNext() {
            return false;
        }

        /**
         * Calling this method throws a no-such-element exception.
         *
         * @return Always throws an exception.
         * @throws NoSuchElementException Always.
         */
        public E next() {
            String msg = "No elements in empty iterator.";
            throw new NoSuchElementException(msg);
        }

        /**
         * Calling this method throws an illegal state exception.
         *
         * @throws IllegalStateException Always.
         */
        public void remove() {
            String msg = "No elements to remove in empty iterator.";
            throw new IllegalStateException(msg);
        }

    }

    /**
     * An <code>Iterator.Singleton</code> is an iterator over a
     * singleton object.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe2.0
     * @param <E> the type of objects returned by the iterator
     */
    static class Singleton<E> implements Iterator<E> {

        /**
         * The single object to return.
         */
        private E mMember;

        /**
         * <code>true</code> if the single element has not already
         * been returned.
         */
        private boolean mHasNext = true;

        /**
         * Construct a singleton iterator that returns the specified
         * object.
         *
         * @param member Single member over which to iterate.
         */
        public Singleton(E member) {
            mMember = member;
        }

        /**
         * Returns <code>true</code> if the single member has not
         * already been returned.
         *
         * @return <code>true</code> if the single member has not
         * already been returned.
         */
        public boolean hasNext() {
            return mHasNext;
        }

        /**
         * Returns the singleton member if it has not yet been
         * returned, otherwise throw an exception.
         *
         * @return Singleton member if it has not yet been returned.
         * @throws NoSuchElementException If the singleton member has
         * already been returned and no elements remain.
         */
        public E next() {
            if (!mHasNext)
                throw new NoSuchElementException();
            mHasNext = false;
            E result = mMember;
            mMember = null;
            return result;
        }

        /**
         * Throws an unsupported operation exception.
         *
         * @throws UnsupportedOperationException Whenver called.
         */
        public void remove() {
            String msg = "This iterator does not support remove()."
                + " class=" + this.getClass();
            throw new UnsupportedOperationException(msg);
        }
    }


    /**
     * An <code>Iterators.Pair</code> provides an iterator
     * over a sequence of exactly two elements.
     *
     * @author  Bob Carpenter
     * @version 3.0
     * @since   LingPipe2.0
     * @param <E> the type of objects returned by the iterator
     */
    static class Pair<E> implements Iterator<E> {

        /**
         * Number of members returned so far.
         */
        private int mMembersReturned = 0;

        private E mMember1;
        private E mMember2;

        /**
         * Construct a pair iterator based on the containing
         * pair set.
         *
         * @param member1 First member.
         * @param member2 Second member.
         */
        public Pair(E member1, E member2) {
            mMember1 = member1;
            mMember2 = member2;
        }

        /**
         * Returns <code>true</code> if there are more elements
         * left to return.
         *
         * @return <code>true</code> if there are more elements
         * left to return.
         */
        public boolean hasNext() {
            return mMembersReturned < 2;
        }

        /**
         * Returns the next object in this pair iterator,
         * or throws an exception if there aren't any more.
         *
         * @return Next object in this pair iterator.
         */
        public E next() {
            if (mMembersReturned == 0) {
                ++mMembersReturned;
                E result1 = mMember1;
                mMember1 = null;
                return result1;
            }
            if (mMembersReturned == 1) {
                ++mMembersReturned;
                E result2 = mMember2;
                mMember2 = null;
                return result2;
            }
            throw new NoSuchElementException();
        }

        /**
         * Throws an unsupported operation exception.
         *
         * @throws UnsupportedOperationException Whenver called.
         */
        public void remove() {
            String msg = "This iterator does not support remove()."
                + " class=" + this.getClass();
            throw new UnsupportedOperationException(msg);
        }

    }


    /**
     * An <code>Iterators.Filter</code> filters the stream of objects
     * returned by another iterator by subjecting them to an acceptance
     * test.  Instances are constructed with a specified iterator to be
     * filtered; this filter is saved in this class and should not be
     * accessed by other methods.  Concrete subclasses must implement
     * {@link #accept(Object)}, which determines which of the elements
     * produced by the containediterator are returned.
     *
     * @author  Bob Carpenter
     * @version 3.0
     * @since   LingPipe1.0
     * @param <E> the type of objects returned by the iterator
     */
    public static abstract class Filter<E> implements Iterator<E> {

        private final Iterator<? extends E> mIterator;
        private boolean mFoundNext = false;
        private E mNext;

        /**
         * Construct a filtered iterator from the specified iterator.
         *
         * @param iterator Contained iterator to be filtered.
         */
        public Filter(Iterator<? extends E> iterator) {
            mIterator = iterator;
        }

        /**
         * Returns <code>true</code> for objects returned by the contained
         * iterator that should be returned by this iterator.
         *
         * @param x Object to test.
         * @return <code>true</code> if this object should be returned by
         * this iterator.
         */
        abstract public boolean accept(E x);

        /**
         * Returns <code>true</code> if calls to <code>next()</code> will
         * return a value.
         *
         * <P><i>Implementation note:</i> This iterator stores the next
         * element in a local variable after calls to this method.  Calls to
         * {@link #next()} remove this reference.
         *
         * @return <code>true</code> if calls to <code>next()</code> will
         * return a value.
         */
        public boolean hasNext() {
            if (mFoundNext) return true;
            while (mIterator.hasNext()) {
                E y = mIterator.next();
                if (accept(y)) {
                    mFoundNext = true;
                    mNext = y;
                    return true;
                }
            }
            return false;
        }


        /**
         * Returns the next value from the contained iterator that is accepted.
         * Acceptance is determined by the method {@link #accept(Object)}.
         *
         * @return Next object from the underlying iterator that passes
         * the acceptance test.
         * @throws NoSuchElementException If there are no more elements in
         * the underlying iterator that pass the acceptance test.
         */
        public E next() {
            if (!hasNext())
                throw new NoSuchElementException();
            mFoundNext = false;
            E result = mNext;
            mNext = null;
            return result;
        }

        /**
         * This operation is not supported.
         *
         * <P><i>Implementation Note:</i> Because calls to {@link
         * #hasNext()} must iterate over the contained iterator to find
         * the next acceptable object to return, it is not guaranteed that
         * the last element returned by this iterator is the same as the
         * last element returned by the underlying iterator.  Thus the
         * underlying iterator can't be used to do the removal without
         * tripping the fail-fast behavior of {@link Iterator}.
         *
         * @throws UnsupportedOperationException Always.
         */
        public void remove() {
            String msg = "Cannot remove from a filtered iterator.";
            throw new UnsupportedOperationException(msg);
        }

    }


    /**
     * An <code>Iterator.Modifier</code> uses a single abstract method
     * to operate on the elements returned by an underlying iterator
     * to return modified objects.  The {@link #remove()} and {@link
     * #hasNext()} methods are simply passed to the underlying iterator.
     * This implements the filter pattern, which is known as a map in
     * functional programming.
     *
     * @author  Bob Carpenter
     * @version 3.0
     * @since   LingPipe2.1
     * @param <E> the type of objects returned by the iterator
     */
    public static abstract class Modifier<E> implements Iterator<E> {
        private final Iterator<? extends E> mIt;

        /**
         * Construct a modifier from an underlying iterator.
         *
         * @param it Underlying iterator.
         */
        public Modifier(Iterator<? extends E> it) {
            mIt = it;
        }

        /**
         * Remove the next element by delegating the call to the the
         * underlying iterator.
         */
        public void remove() {
            mIt.remove();
        }

        /**
         * Returns <code>true</code> if the underlying iterator has
         * more elements.  This method is simply delegated to the
         * underlying iterator.
         *
         * @return <code>true</code> if this iterator has more
         * elements.
         */
        public boolean hasNext() {
            return mIt.hasNext();
        }

        /**
         * Returns the next element for this iterator, which is
         * the object returned by the underlying iterator after
         * undergoing modification by {@link #modify(Object)}.
         *
         * @return The modified next element from the underlying
         * iterator.
         */
        public E next() {
            return modify(mIt.next());
        }

        /**
         * This abstract method is applied to objects returned by the
         * underlying iterator to create the object returned by this
         * iterator. This method is called once for each call to
         * {@link #next()}.
         *
         * @param next Object returned by underlying iterator.
         * @return Object returned by this iterator.
         */
        public abstract E modify(E next);

    }

    /**
     * An <code>Iterators.Buffered</code> uses a single method to return
     * objects, buffering the result and returning it as the next element
     * if it is non-<code>null</code>.  This class does not support
     * <code>null</code> return values for {@link #next()}.  The {@link
     * #remove()} operation is unsupported, but may be overridden.
     *
     * @author  Bob Carpenter
     * @version 3.0
     * @since   LingPipe1.0
     * @param <E> the type of objects returned by the iterator
     */
    public static abstract class Buffered<E> implements Iterator<E> {

        private E mNext;

        /**
         * Construct a buffered iterator.  This constructor does not
         * do anything.
         */
        protected Buffered() {
            // do nothing
        }

        /**
         * Returns the next object for this iterator, or <code>null</code>
         * if there are no more objects.
         *
         * @return Next object for this iterator.
         */
        protected abstract E bufferNext();

        /**
         * Returns <code>true</code> if the next call to {@link #next()}
         * will return a non-<code>null</code> value.
         *
         * @return <code>true</code> if the next call to {@link #next()}
         * will return a non-<code>null</code> value.
         */
        public boolean hasNext() {
            return mNext != null
                || (mNext = bufferNext()) != null;
        }

        /**
         * Returns the next object for this iterator.
         *
         * @return The next object for this iterator.
         * @throws NoSuchElementException If there are no more elements.
         */
        public E next() {
            if (!hasNext())
                throw new NoSuchElementException();
            E result = mNext;
            mNext = null;
            return result;
        }

        /**
         * Throws an unsupported operation exception unless overridden by
         * a subclass.
         *
         * @throws UnsupportedOperationException Always.
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }

    }


    /**
     * An <code>Iterators.Sequence</code> iterates over the elements of an
     * ordered sequence of iterators in turn.  Each iterator is exhausted
     * before moving to the next.  These iterators may be supplied as a
     * pair of iterators, as an array of iterators, or as an iterator of
     * iterators.  The sequence iterator delegates calls to {@link
     * #next()} and {@link #remove()} to the relevant iterator in the
     * underlying sequence of iterators.  For <code>next()</code>, this is
     * the current underlying iterator.  For <code>remove()</code>, it's
     * the last iterator whose <code>next()</code> element was called, and
     * it throws an illegal state exception if there isn't one.
     *
     * <P><I>Implementation Note:</I> Because of the requirements of
     * {@link Iterator#remove()}, a reference to the last iterator is
     * kept, as well as to the current iterator.  Otherwise, the sequence
     * iterator will release resources as soon as possible.  If the
     * supplied sequence is an array, the elements will not be
     * automatically returned from that array; it is simply wrapped in an
     * instance of {@link Iterators.Array}.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe1.0
     * @param <E> the type of objects returned by the iterator
     */
    static class Sequence<E> implements Iterator<E> {

        private final Iterator<? extends Iterator<? extends E>> mIterators;
        private Iterator<? extends E> mCurrentIterator;
        private Iterator<? extends E> mLastIteratorNextCalled;

        /**
         * Construct a sequenc iterator that calls the pair of
         * iterators specified in turn.
         *
         * @param iterator1 First iterator.
         * @param iterator2 Second iterator.
         */
        public Sequence(Iterator<? extends E> iterator1,
                        Iterator<? extends E> iterator2) {
            this(toIteratorIterator(iterator1,iterator2));
        }


        /**
         * Construct a sequence iterator that calls the iterators in the
         * specified array in the order they are given in the array.
         *
         * @param iterators Sequence of iterators.
         */
        public Sequence(Iterator<? extends E>[] iterators) {
            this(new Iterators.Array<Iterator<? extends E>>(iterators));
        }

        /**
         * Construct a sequence iterator that calls the iterators returned
         * by the iterator of iterators specified.  If one of the elements
         * is not an iterator, <code>hasNext()</code> and
         * <code>next()</code> will throw a
         * <code>ClassCastException</code>.
         *
         * @param iteratorOfIterators Iterator of iterators.
         */
        public Sequence(Iterator<? extends Iterator<? extends E>> iteratorOfIterators) {
            mIterators = iteratorOfIterators;
        }

        /**
         * Returns <code>true</code> if this iterator has another element.
         * This sequence of iterators has another element if it has
         * another iterator that has another element.
         *
         * @return <code>true</code> if this sequence of iterators
         * has another iterator with another element.
         * @throws ClassCastException If an object is returned by
         * the iterator of iterators specified at construction time
         * that is not an iterator.
         */
        public boolean hasNext() {
            if (mCurrentIterator == null)
                nextIterator(); // get started
            for (; mCurrentIterator != null; nextIterator())
                if (mCurrentIterator.hasNext())
                    return true;
            return false;
        }

        /**
         * Return the next element returned by the next iterator in the
         * iterator sequence.
         *
         * @return The next object in the iteration.
         * @throws ClassCastException If an object is returned by
         * the iterator of iterators specified at construction time
         * that is not an iterator.
         */
        public E next() {
            if (!hasNext())
                throw new NoSuchElementException();
            mLastIteratorNextCalled = mCurrentIterator;
            return mCurrentIterator.next();
        }

        /**
         * Removes the last element returned by this iterator from the
         * collection underlying the iterator from which it was returned.
         * The method can only be called once per call to
         * <code>next()</code>.

         * @throws IllegalStateException If <code>next()</code> has not
         * yet been called, or <code>remove()</code> method has
         * been called after the last call to <code>next()</code>.
         */
        public void remove() {
            if (mLastIteratorNextCalled == null)
                throw new IllegalStateException("next() not yet called.");
            mLastIteratorNextCalled.remove();
            mLastIteratorNextCalled = null;
        }

        private void nextIterator() {
            // possible cast exception
            mCurrentIterator =
                mIterators.hasNext()
                ? mIterators.next()
                : null;
        }


        static <E> Iterator<? extends Iterator<? extends E>>
            toIteratorIterator(Iterator<? extends E> it1,
                               Iterator<? extends E> it2) {
                ArrayList<Iterator<? extends E>> list
                    = new ArrayList<Iterator<? extends E>>(2);
                list.add(it1);
                list.add(it2);
                return list.iterator();
        }

    }

    /**
     * A {@code Iterators.PrimitiveInt} is an integer iterator that
     * also allows objects to be accessed as primitive {@code int}
     * values.
     *
     * <p>The method {@link #next()} returns an {@code Integer},
     * whereas {@link #nextPrimitive()} returns a primitive {@code
     * int} value.  Using either one will advanced the iterator to the
     * next element.
     *
     * <p><i>Implementation Note:</i> Using the standard iterator
     * implementation as {@code Integer} requires boxing of the
     * primitive values as objects.  Therefore, use the method
     * {@code nextPrimitive()} wherever possible.
     *
     * @author Mike Ross
     * @author Bob Carpenter
     * @version 3.8
     * @since Lingpipe3.8
     */
    public static abstract class PrimitiveInt
        implements Iterator<Integer> {

        /**
         * Returns the next primitive integer.
         *
         * @return The next primitive integer.
         */
        abstract public int nextPrimitive();

        /**
         * Returns {@code true} if there is another integer in the
         * iteration.
         *
         * @return {@code true} if there is another integer in the
         * iteration.
         */
        abstract public boolean hasNext();

        /**
         * Throws unsupported operation exception.
         *
         * @throws UnsupportedOperationException Always.
         */
        public void remove() {
            String msg = "Iterators.PrimitiveInt does not support remove.";
            throw new UnsupportedOperationException(msg);
        }

        /**
         * Returns the next integer result.
         *
         * <p><i>Implementation Note:</i> Requires boxing the
         * primitive {@code int} returned by {@link #nextPrimitive()}.
         *
         * @return The next integer.
         */
        public Integer next() {
            return nextPrimitive();
        }
    }


    /**
     * Construct an Integer iterator from 0 (inclusive) the specified
     * end point (exclusive).  The returned iterator does not support
     * {@code remove()}.
     *
     * @param end One plus the last integer returned.
     */
    public static PrimitiveInt intRange(int end) {
        return new IntRange(0,end);
    }


    /**
     * Returns a newly constructed primitive integer iterator that
     * iterates from the start (inclusive) to end (exclusive).
     *
     * <p>The returned iterator does not support {@code remove()}.
     *
     * @param start The first and lowest value to return.
     * @param end One plus the last integer returned.
     * @throws IllegalArgumentException If {@code start > end}.
     */
    public static PrimitiveInt intRange(int start, int end) {
        return new IntRange(start,end);
    }

    /**
     * Returns an iterator over the array of primitive integers
     * specified.  
     *
     * <p>There are no order restrictions on the array -- its elements
     * may be in any order and may contain duplicates.
     *
     * <p>The returned iterator does not support {@code remove()}.
     *
     * @param members Array of members to iterate.
     */
    public static PrimitiveInt intArray(int[] members) {
        return new IntArray(members);
    }


    /**
     * See {@link #intRange(int,int)} for usage.
     *
     * @author  Mike Ross
     * @version 3.8
     * @since   Lingpipe3.8
     */
    static class IntRange extends PrimitiveInt {
        private int mCur;
        private final int mEnd;
        public IntRange(int start, int end) {
            if (end < start) {
                String msg = "End point must be >= start point."
                    + " Found start=" + start
                    + " end=" + end;
                throw new IllegalArgumentException(msg);
            }
            mCur = start;
            mEnd = end;
        }
        public boolean hasNext() {
            return mCur < mEnd;
        }
        public int nextPrimitive() {
            if (!hasNext())
                throw new NoSuchElementException();
            return mCur++;
        }
    }

    /**
     * See {@link #intArray(int[])} for usage.
     *
     * @author  Mike Ross
     * @version 3.8
     * @since   Lingpipe3.8
     */
    static class IntArray extends PrimitiveInt {
        private final int[] mMembers;
        private int mPosition;
        public IntArray(int[] members) {
            mMembers = members;
        }
        public boolean hasNext() {
            return mPosition < mMembers.length;
        }
        public int nextPrimitive() {
            if (!hasNext())
                throw new NoSuchElementException();
            return mMembers[mPosition++];
        }

    }

}

   
    
    
    
    
    
    
  








Related examples in the same category

1.Listing the Elements of a Collection
2.De-mystify the Iterator interface, showing how to write a simple Iterator for an Array of Objects
3.Iterate over Set
4.Demonstrate iterators.
5.Use the for-each for loop to cycle through a collection.
6.List IteratorList Iterator
7.Iterate a Collection and remove an item (Exception, wrong version)
8.Use an Iterator and remove the item with Iterator.remove()
9.An Iterator wrapper for an Enumeration.
10.EmptyIterator is an iterator which is empty.
11.Implements an java.util.Iterator over any array
12.Treat an Iterator as an Iterable
13.Iterator class for sparse values in an array.
14.Iterator class for values contained in an array range.
15.Array Iterator
16.Cyclic Iteration
17.Create singleton Iterator
18.Empty Iterator
19.An Iterator that wraps a number of Iterators
20.An Iterator to iterate over the elements of an array
21.Sorted Iterator
22.Iterator Union of Iterators
23.Iterator Utils
24.Linked Iterator
25.Prefetch Iterator
26.Protects an given iterator by preventing calls to remove().
27.An Iterator that returns the elements of a specified array, or other iterators etc.
28.An Iterator wrapper for an Object[], allow us to deal with all array like structures in a consistent manner.
29.An array iterator
30.Adapt iterator to iterable
31.Iterator Collection
32.Convert Iterable to List
33.A singleton null object Iterator implementation.