Подтвердить что ты не робот

Улучшенная коллекция Итератор

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

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

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

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

Спасибо заранее, Дон

4b9b3361

Ответ 2

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

Peek в этой точке легко реализовать, выполнив

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

http://clojure.org/sequences

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

Я никогда не сталкивался с проблемой, когда мне нужен peek(); Итератор отлично справился со мной. Мне любопытно, как вы используете итераторы, что вам кажется, что вам нужна эта добавленная функциональность.

Ответ 10

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

Ответ 11

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

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