Java для каждого, но несколько типов итераторов? - PullRequest
5 голосов
/ 15 сентября 2010

У меня есть класс Polygon, в котором я хочу реализовать два итератора: один для прохождения всех элементов (вершин и ребер в чередующемся порядке) только ОДИН РАЗ, а другой - для бесконечного (циклического) их прохождения.

С точки зрения использования для каждого, я предполагаю, что я смогу использовать только один из перечисленных выше итераторов по умолчанию, который можно использовать для for-each, посредством реализации Iterable.iterator().Это правильно?Или есть способ, которым я мог бы использовать для каждого из них?

Ответы [ 2 ]

11 голосов
/ 15 сентября 2010

Просто добавьте два метода, возвращающих два разных итератора, по одному для каждого случая:

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

        }
    };
}

Это всего лишь пример со списком строк, просто адаптируйте.

Вместо

for (Polygon p : polygons) { }

просто используйте

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

или циклическое издание

3 голосов
/ 15 сентября 2010

Ответ, который я думаю, лучше, чем уже представленный, - это метод, который превращает любой Iterable в циклический.

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); }
    };
  }
}

Тогда вы можете просто реализовать один метод итератора в классе Polygon и использовать

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

для итерации один раз и

для (Элемент e: цикл (многоугольник)) {...}

для итерации бесконечно.В качестве бонуса модификатор цикла может быть применен к любой итерации.

...