Collections Data Structure Java

/*
 * 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 EMPTY_ITERATOR
        = new Empty();
    /**
     * 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  Iterator empty() {
        @SuppressWarnings("unchecked")
        Iterator emptyIterator = (Iterator) 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  Iterator singleton(E e) {
        Iterator singletonIterator = new Singleton(e);
        return singletonIterator;
    }
    /**
     * Returns a newly constructed iterator over the specified pair of
     * elements.
     *
     * 

Implementation Note: 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  Iterator pair(E e1, E e2) {
        return new Pair(e1,e2);
    }
    /**
     * Returns an iterator constructed from the specified variable
     * length argument list of objects.  
     *
     * 

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  Iterator list(E... es) {
        return java.util.Arrays.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  Iterator unmodifiable(Iterator it) {
        final Iterator mIt = it;
        return new Iterator() {
            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.
     *
     * 

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  Iterator sequence(Iterator it1,
                                           Iterator it2) {
        Iterator result = new Sequence(it1,it2);
        return result;
    }
    public static  Iterator sequence(List> iterators) {
        @SuppressWarnings({"unchecked","rawtypes"})
        Iterator[] elts
            = (Iterator[]) iterators.toArray(new Iterator[0]);
        Iterator it = new Sequence(elts);
        return it;
    }
    public static  Iterator
        sequence(Iterator> iteratorOfIterators) {
        Iterator it = new Sequence(iteratorOfIterators);
        return it;
    }
    /**
     * Returns an iterator over the specified array of objects.
     *
     * 

Warning: The array is not copied, so any changes in
     * the underlying array are reflected in the iterator.
     *
     * 

Implementation Note: 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  Iterator array(E[] members) {
        return new Array(members);
    }
    /**
     * Returns a newly constructed iterator over the specified
     * object array slice.
     *
     * 

The {@code remove()} method is not supported.
     *
     * 

Warning: The array is not copied, so any changes in
     * the underlying array are reflected in the iterator.
     *
     * 

Implementation Note: 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  Iterator arraySlice(E[] members, int start, int length) {
        return new ArraySlice(members,start,length);
    }
    /**
     * An Iterator.Array iterates over the elements of an
     * array specified at construction time.
     *
     * 

Implementation Note: 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 remove() after ever next()
     * will free the references in the array.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe1.0
     * @param  the type of objects returned by the iterator
     */
    static class Array implements Iterator {
        /**
         * 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 true if this iterator has more
         * elements.
         *
         * @return true 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 null.
         *
         * @throws IllegalStateException If the next
         * method has not been called, or the remove
         * 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 Iterators.ArraySlice iterates over a slice of
     * an array specified by start index and length.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe1.0
     * @param  the type of objects returned by the iterator
     */
    static class ArraySlice implements Iterator {
        /**
         * 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 true if there are more objects
         * to return.
         *
         * @return true 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 UnsupportedOperationException.
         *
         * @throws UnsupportedOperationException If called.
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }
    /**
     * An Iterator.Empty is an iterator with no
     * objects.  The method {@link #hasNext()} always returns
     * false, while the methods {@link #next()}
     * and {@link #remove()} always throw exceptions.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe3.0
     * @param  the type of objects returned by the iterator
     */
    static class Empty implements Iterator {
        /**
         * Construct an empty iterator.
         */
        public Empty() {
            /* do nothing */
        }
        /**
         * Always returns false.
         *
         * @return false.
         */
        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 Iterator.Singleton is an iterator over a
     * singleton object.
     *
     * @author  Bob Carpenter
     * @version 3.8
     * @since   LingPipe2.0
     * @param  the type of objects returned by the iterator
     */
    static class Singleton implements Iterator {
        /**
         * The single object to return.
         */
        private E mMember;
        /**
         * true 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 true if the single member has not
         * already been returned.
         *
         * @return true 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 Iterators.Pair provides an iterator
     * over a sequence of exactly two elements.
     *
     * @author  Bob Carpenter
     * @version 3.0
     * @since   LingPipe2.0
     * @param  the type of objects returned by the iterator
     */
    static class Pair implements Iterator {
        /**
         * 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 true if there are more elements
         * left to return.
         *
         * @return true 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 Iterators.Filter 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  the type of objects returned by the iterator
     */
    public static abstract class Filter implements Iterator {
        private final Iterator 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 iterator) {
            mIterator = iterator;
        }
        /**
         * Returns true for objects returned by the contained
         * iterator that should be returned by this iterator.
         *
         * @param x Object to test.
         * @return true if this object should be returned by
         * this iterator.
         */
        abstract public boolean accept(E x);
        /**
         * Returns true if calls to next() will
         * return a value.
         *
         * 

Implementation note: This iterator stores the next
         * element in a local variable after calls to this method.  Calls to
         * {@link #next()} remove this reference.
         *
         * @return true if calls to next() 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.
         *
         * 

Implementation Note: 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 Iterator.Modifier 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  the type of objects returned by the iterator
     */
    public static abstract class Modifier implements Iterator {
        private final Iterator mIt;
        /**
         * Construct a modifier from an underlying iterator.
         *
         * @param it Underlying iterator.
         */
        public Modifier(Iterator it) {
            mIt = it;
        }
        /**
         * Remove the next element by delegating the call to the the
         * underlying iterator.
         */
        public void remove() {
            mIt.remove();
        }
        /**
         * Returns true if the underlying iterator has
         * more elements.  This method is simply delegated to the
         * underlying iterator.
         *
         * @return true 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 Iterators.Buffered uses a single method to return
     * objects, buffering the result and returning it as the next element
     * if it is non-null.  This class does not support
     * null 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  the type of objects returned by the iterator
     */
    public static abstract class Buffered implements Iterator {
        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 null
         * if there are no more objects.
         *
         * @return Next object for this iterator.
         */
        protected abstract E bufferNext();
        /**
         * Returns true if the next call to {@link #next()}
         * will return a non-null value.
         *
         * @return true if the next call to {@link #next()}
         * will return a non-null 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 Iterators.Sequence 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 next(), this is
     * the current underlying iterator.  For remove(), it's
     * the last iterator whose next() element was called, and
     * it throws an illegal state exception if there isn't one.
     *
     * 

Implementation Note: 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  the type of objects returned by the iterator
     */
    static class Sequence implements Iterator {
        private final Iterator> mIterators;
        private Iterator mCurrentIterator;
        private Iterator 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 iterator1,
                        Iterator 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[] iterators) {
            this(new Iterators.Array>(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, hasNext() and
         * next() will throw a
         * ClassCastException.
         *
         * @param iteratorOfIterators Iterator of iterators.
         */
        public Sequence(Iterator> iteratorOfIterators) {
            mIterators = iteratorOfIterators;
        }
        /**
         * Returns true if this iterator has another element.
         * This sequence of iterators has another element if it has
         * another iterator that has another element.
         *
         * @return true 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
         * next().
         * @throws IllegalStateException If next() has not
         * yet been called, or remove() method has
         * been called after the last call to next().
         */
        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  Iterator>
            toIteratorIterator(Iterator it1,
                               Iterator it2) {
                ArrayList> list
                    = new ArrayList>(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.
     *
     * 

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.
     *
     * 

Implementation Note: 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 {
        /**
         * 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.
         *
         * 

Implementation Note: 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).
     *
     * 

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.  
     *
     * 

There are no order restrictions on the array -- its elements
     * may be in any order and may contain duplicates.
     *
     * 

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++];
        }
    }
}