Почему Итератор Java не является Iterable?



Answers

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

Например, я обычно могу написать:

public void iterateOver(Iterable<String> strings)
{
    for (String x : strings)
    {
         System.out.println(x);
    }
    for (String x : strings)
    {
         System.out.println(x);
    }
}

Это должно печатать коллекцию дважды - но с вашей схемой второй цикл всегда заканчивается мгновенно.

Question

Почему интерфейс Iterator не расширяет Iterable ?

Метод iterator() может просто вернуть this .

Это специально или просто надзор над дизайнерами Java?

Было бы удобно использовать цикл for-each с итераторами следующим образом:

for(Object o : someContainer.listSomeObjects()) {
    ....
}

где listSomeObjects() возвращает итератор.




Как отмечают другие, Iterator и Iterable - две разные вещи.

Кроме того, реализация Iterator предшествует расширению для циклов.

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

for (String line : in(lines)) {
  System.out.println(line);
}

Пример реализации:

  /**
   * Adapts an {@link Iterator} to an {@link Iterable} for use in enhanced for
   * loops. If {@link Iterable#iterator()} is invoked more than once, an
   * {@link IllegalStateException} is thrown.
   */
  public static <T> Iterable<T> in(final Iterator<T> iterator) {
    assert iterator != null;
    class SingleUseIterable implements Iterable<T> {
      private boolean used = false;

      @Override
      public Iterator<T> iterator() {
        if (used) {
          throw new IllegalStateException("SingleUseIterable already invoked");
        }
        used = true;
        return iterator;
      }
    }
    return new SingleUseIterable();
  }

В Java 8 адаптация Iterator к Iterable упрощается:

for (String s : (Iterable<String>) () -> iterator) {



Для простоты Iterator и Iterable - две разные концепции, Iterable - это просто сокращение для «Я могу вернуть итератор». Я думаю, что ваш код должен быть:

for(Object o : someContainer) {
}

с someContainer instanceof SomeContainer extends Iterable<Object>




Я согласен с принятым ответом, но хочу добавить свое собственное объяснение.

  • Итератор представляет состояние пересечения, например, вы можете получить текущий элемент из итератора и перейти к следующему.

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

Было бы неплохо, если Java for loop принимает как Iterator, так и Iterable.




Iterator - это интерфейс, который позволяет вам перебирать что-то. Это реализация движения через какую-то коллекцию.

Iterable - это функциональный интерфейс, который означает, что что-то содержит доступный итератор.

В Java8 это делает жизнь довольно легкой ... Если у вас есть Iterator но вам нужен Iterable вы можете просто сделать:

Iterator<T> someIterator;
Iterable<T> = ()->someIterator;

Это также работает в for-loop:

for (T item : ()->someIterator){
    //doSomething with item
}



Я также вижу, что многие это делают:

public Iterator iterator() {
    return this;
}

Но это не делает это правильно! Этот метод не будет тем, что вы хотите!

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

public class IterableIterator implements Iterator, Iterable {

  //Constructor
  IterableIterator(IterableIterator iter)
  {
    this.initdata = iter.initdata;
  }
  // methods of Iterable

  public Iterator iterator() {
    return new MyClass(this.somedata);
  }

  // methods of Iterator

  public boolean hasNext() {
    // ...
  }

  public Object next() {
    // ...
  }

  public void remove() {
    // ...
  }
}

Возникает вопрос: можно ли каким-либо образом сделать абстрактный класс таким? Чтобы получить IterableIterator, нужно только реализовать два метода next () и hasNext ()




В соответствующей заметке вы можете найти адаптер IteratorIterable в Apache Commons Collections4 полезным. Просто создайте экземпляр из итератора, и у вас есть соответствующий итерабельный.

IteratorIterable

ID: org.apache.commons: commons-collections4: 4.0




Related