6

I have a class Polygon on which I wish to implement two iterators: one to run through all elements (vertices and edges in alternating order) just ONCE, and another to run through them ad infinitum (cyclically).

From a for-each usage standpoint, my guess is that I am only going to be able to have one of the above be the default iterator that can be used with for-each, via implementation of Iterable.iterator(). Is this correct? Or is there a way I could use for-each with both?

2 Answers 2

12

Just add two methods returning two different Iterators, one for each case:

public Iterable<String> eachOnce() {
    List<String> allResults = new ArrayList<String>();
    // fill list
    return allResults;
}

public Iterable<String> eachCyclic() {
    return new Iterable<String>() {

        public Iterator<String> iterator() {
            return new Iterator<String>() {

                public boolean hasNext() {
                    return true;
                }

                public String next() {
                    // TODO implement
                    return null;
                }

                public void remove() {
                    // do nothing
                }
            };

        }
    };
}

This is just an example with a List of Strings, just adapt.

Instead of

for (Polygon p : polygons) { }

just use

for (Polygon p : polygons.eachOnce()) { }

or the cyclic edition

Sign up to request clarification or add additional context in comments.

2 Comments

Nice one GHad, I'm glad I asked. This keeps the ease of use of for-each and doesn't break encapsulation to get around the problem.
+1 This is essentially the same as what java.util.Map does - you can call entrySet(), keySet() or values(), which all return various Iterables.
3

An answer I think is better than those already presented is a method that turns any Iterable into a cyclic one.

public class IterableUtils {
  public static class CyclicIterator<T> implements Iterator<T> {
    private final Iterable<T> inner;
    private Iterator<T> currentIter;
    public CyclicIterator(Iterable<T> inner) {
      this.inner = inner;
    }
    public boolean hasNext() {
      if (currentIter == null || !currentIter.hasNext()) {
        currentIter = inner.iterator();
      }
      return currentIter.hasNext();
    }
    public T next() {
      if (currentIter == null || !currentIter.hasNext()) {
        currentIter = inner.iterator();
      }
      return currentIter.next();
    }
    public void remove() {
      currentIter.remove();
    }
  }
  public static <T> Iterable<T> cycle(final Iterable<T> i) {
    return new Iterable<T>() {
      public Iterator<T> iterator() { return new CyclicIterator<T>(i); }
    };
  }
}

Then you can just implement the single iterator method in the Polygon class and use

for (Element e: polygon) {
  ...
}

to iterate once and

for (Element e: cycle(polygon)) { ... }

to iterate endlessly. As a bonus, the cycle modifier can be applied to any iterable.

1 Comment

A nice alternative, Geoff. I may use this in future.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.