Several separate Java projects have led to using the same simple Iterator implementation, AbstractFilterIterator. The idea is very simple: use a single method to filter an underlying Iterator and decide which subset of the data to reveal. Perhaps it is more easily shown than explained, at least for me:
/*
* AbstractFilterIterator.java
* Copyright 2003 (C) B. K. Oxley (binkley)
* <binkley@alumni.rice.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* Created on July 15, 2003.
*
* $Id: AbstractFilterIterator.java,v 1.1 2003/08/28 19:07:52 binkley Exp $
*/
package hm.binkley.util;
import java.util.Iterator;
import java.util.ListIterator;
/**
* <code>AbstractFilterIterator</code> is a partial list iterator.
*
* @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
* @version 1.0
*/
public abstract class AbstractFilterIterator
implements Iterator {
/** <code>ListIterator</code> through the elements. */
protected ListIterator it;
/** The current element after {@link #next()}. */
protected Object cursor = null;
/**
* Construct an <code>AbstractFilterIterator</code> from an
* underlying iterator over a range.
*
* @param it the underlying iterator
*
*/
protected AbstractFilterIterator(ListIterator it) {
this.it = it;
}
/**
* Match <var>element</var>. If the match is
* <code>true</code>, <code>AbstractFilterIterator</code> will
* present <var>element</var> in the view of the underlying
* iterator.
*
* @param element the element to match
* @return <code>true</code> if the element matches
*/
protected abstract boolean match(Object element);
/**
* Scroll the underlying iterator forward to find the next match.
* Afterwards, use {@link #rewindNext(int)} to return the
* underlying iterator to its original position.
*
* @return boolean <code>true</code> if there is a next match
*/
protected boolean findNext() {
while (it.hasNext())
if (match(it.next()))
return true;
return false;
}
/**
* Return the underlying iterator to previous position after an
* earlier call to {@link #findNext()}.
*
* @param current the previous position
*/
protected void rewindNext(int current) {
for (int next = it.nextIndex(); next > current; --next)
it.previous();
}
/** {@inheritDoc} */
public boolean hasNext() {
// We have do it this way so that you can use next()
// independently of hasNext().
int current = it.nextIndex();
boolean hasNext = findNext();
rewindNext(current);
return hasNext;
}
/** {@inheritDoc} */
public Object next() {
while (!match(cursor = it.next()))
; // nothing
return cursor;
}
/** {@inheritDoc} */
public void remove() {
it.remove();
}
}
As you might suspect, AbstractFilterListIterator is similar and extends AbstractFilterIterator to include methods from ListIterator. This is very straight-forward as AbstractFilterIterator already has a protected ListIterator member, it, to work with.