An implementation example of the ProposedIterator from IteratorSemanticsAreWrong
class ProposedIterator { private Iterator wrappedIterator = null; private Object currentObject = null; private boolean isValid = false; public ProposedIterator(Iterator aIterator) { wrappedIterator = aIterator; try { currentObject = wrappedIterator.next(); isValid = true; } catch (NoSuchElementException nsee) { currentObject = null; isValid = false; } } public void next() { if (isValid) { try { currentObject = wrappedIterator.next(); } catch (NoSuchElementException nsee) { currentObject = null; isValid = false; } } } public Object get() { if (isValid) { return currentObject; } else { throw new IllegalStateException(); } } public boolean isValid() { return isValid; } }Example use of ProposedIterator
public int countCommonElementsRevision3(Iterator it1, Iterator it2, Comparator comparisonStrategy) { ProposedIterator proposedOne = new ProposedIterator(it1); ProposedIterator proposedTwo = new ProposedIterator(it2); int count = 0; // number of common elements while (proposedOne.isValid() && proposedTwo.isValid()) { System.out.println("Comparing: " + proposedOne.get() + " " + proposedTwo.get()); int c = comparisonStrategy.compare(proposedOne.get(), proposedTwo.get()); if (c == 0) { count++; proposedOne.next(); proposedTwo.next(); } else if (c > 0) { proposedTwo.next(); } else { proposedOne.next(); } } return count; }--KentDorsey
See also one ugly attempt to code a QueryableIterator and its utilization.
This implementation uses exceptions in normal program flow, which is in general an absolutely horrible idea. Instantiating an exception is very slow, so it should never have to happen unless the program state involved is actually exceptional in some way.
Here's an alternate implementation with some simple changes to avoid this problem:
class ProposedIterator<T> { private final Iterator<? extends T> wrappedIterator; private T currentObject = null; private boolean isValid = false; public ProposedIterator(Iterator<? extends T> anIterator) { wrappedIterator = anIterator; isValid = wrappedIterator.hasNext(); currentObject = isValid ? wrappedIterator.next() : null; } public void next() { if (!isValid) return; if (wrappedIterator.hasNext()) { currentObject = wrappedIterator.next(); } else { currentObject = null; isValid = false; } } public T get() { if (isValid) return currentObject; else throw new NoSuchElementException(); } public boolean isValid() { return isValid; } }
The original example illustrated CommandQuerySeparation by demonstrating explicit wrapping of exceptions and was never meant for production use. Thanks for the simplification.
Hey, (first change!) I used the ProposedIterator in a project, and realized there's a bug (feature?) in the constructor. The code is iterated directly in the constructor, which means upon first use the user will have to use get. This is a different behavior than Enumeration, Iteration in Java, where you get the first value upon the first call to next(). Anyway, just thought I'd drop you a line and point that out... this is a great wiki, it's such a time saver.