улучшенный сборник Iterator - PullRequest
       11

улучшенный сборник Iterator

12 голосов
/ 10 октября 2008

Лично я нахожу диапазон функций, предоставляемых java.util.Iterator, довольно жалким. Как минимум, я хотел бы иметь такие методы, как:

  • peek () возвращает следующий элемент без перемещения итератора вперед
  • previous () возвращает предыдущий элемент

Хотя есть много других возможностей, таких как first () и last ().

Кто-нибудь знает, существует ли такой сторонний итератор? Вероятно, его необходимо реализовать в качестве декоратора java.util.Iterator, чтобы он мог работать с существующими коллекциями java. В идеале это должен быть «дженерик».

Заранее спасибо, Дон

Ответы [ 11 ]

10 голосов
/ 10 октября 2008

Вы можете легко получить previous(), просто используя java.util.ListIterator.

Просмотр в этот момент легко реализуется с помощью

public <T> T peek(ListIterator<T> iter) throws NoSuchElementException {
    T obj = iter.next();
    iter.previous();
    return obj;
}

К сожалению, его будет проще использовать в качестве служебного метода, поскольку каждый класс коллекции реализует свои собственные итераторы. Сделать обертку для получения метода peek для каждой коллекции на некотором интерфейсе, таком как MyListIterator, было бы довольно много работы.

8 голосов
/ 10 октября 2008
8 голосов
/ 10 октября 2008

Я думаю, что причина, по которой они не реализованы, заключается в том, что они нетривиальны для некоторых коллекций и могут оказать значительное влияние на производительность. Я думаю, вам было бы довольно просто сделать эту работу для коллекций, которые вам небезразличны.

Мне также не нравится, что итераторы Java не могут получить текущее значение, не перемещая его (и поэтому вы не можете легко написать код, который ветвится на основе значения, просто передавая итератор - вы должны передать значение, которое у вас теперь есть).

4 голосов
/ 10 октября 2008

Существует чертова причина, по которой универсальные операторы не реализуют эти функции: они существуют не для всех контейнеров. Типичным примером является контейнер, представляющий некоторый внешний ввод данных, например, файл, рассматриваемый как поток. Каждый раз, когда вы читаете значение, вы потребляете его и перемещаете указатель вперед, если хотите или нет. Если вы наложите эти ограничения на универсальные итераторы, вы потеряете универсальность итераторов.

Если вы хотите использовать метод previous, как предложено, используйте ListIterator<>, который ограничивается контейнером, работающим как списки.

3 голосов
/ 10 октября 2008

Одна вещь, на которую я бы посмотрел, это реализация Seq в clojure

http://clojure.org/sequences

Реализация базовых классов на Java и полный исходный код доступен. Seqs являются декораторами на java-итераторах (берут и реализуют интерфейсы java-итераторов), но они также предоставляют собственный интерфейс, который может быть больше того, что вы хотите, или, по крайней мере, отправную точку.

1 голос
/ 04 ноября 2009

Я видел, что кто-то связался с Google Collections, но никто не упомянул, что метод, который вы ищете, называется Iterators.peekingIterator ().

Тем не менее, было бы лучше, если бы вы могли просто использовать ListIterator.

1 голос
/ 05 марта 2009
public class Iterazor<T> {
  private Iterator<T> it;
  public T top;
  public Iterazor(Collection<T> co) {
    this.it = co.iterator(); 
    top = it.hasNext()? it.next(): null; 
  }
  public void advance() { 
    top = it.hasNext()? it.next(): null; 
  }
}

// usage

for(Iterazor<MyObject> iz = new Iterazor<MyObject>(MyCollection); 
    iz.top!=null; iz.advance())
  iz.top.doStuff();
}
1 голос
/ 10 октября 2008

Как предположил ykaganovich, вы можете попробовать google-collection . Определенно есть некоторая поддержка для некоторых вещей, которые вы хотите, например peeking . Кроме того, как уже упоминали некоторые другие, реализация всех этих вещей для всех коллекций может быть опасной с точки зрения возможности или производительности.

0 голосов
/ 18 ноября 2008

Java-коллекции были написаны для обеспечения минимального набора полезных функций. Это очень хороший подход для кода, который имеет , который должен быть реализован любым, кто реализует Java. Раздувание интерфейса с функциональностью, которая может быть полезной, может привести к значительному увеличению объема кода с улучшениями, замеченными лишь немногими. Если peek () и previous () были частью стандартного итератора, это означает, что каждый, кто пишет новый тип Collection , должен реализовать его, независимо от того, разумно это или нет.

Итераторы также предназначены для работы с вещами, которые физически не могут вернуться назад, делая невозможным оба peek () и previous ().

0 голосов
/ 10 октября 2008

Похоже, вам лучше использовать стек.

...