Создание объектов, реализующих интерфейс Iterable

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

Специализированные объекты составляют костяк любого масштабного приложения. В этом разделе это и рассматривается - концепции и действия по использованию ваших собственных объектов в конструкции for/in.

Для использования цикла for/in необходимо добавить еще один интерфейс - java.lang.Iterable.

package java.lang;

public interface Iterable { public java.util.Iterator iterator(); }

Для обеспечения возможности работы ваших классов или объектов в for/in необходимо реализовать интерфейс Iterable. Есть два основных сценария:

  • Расширить существующий класс коллекции, который уже реализует интерфейс Iterable (и, следовательно, уже поддерживает for/in).

  • Управлять итерацией вручную, определив свою собственную реализацию Iterable.

Пример:

import java.util.Iterator;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * Этот класс предоставляет построчную итерацию по текстовому файлу.
 *   Метод итератора remove() генерирует UnsupportedOperatorException.
 *   Итератор перехватывает и генерирует IOExceptions как IllegalArgumentExceptions.
 */
public class TextFile implements Iterable<String> {

  // Используется в TextFileIterator ниже
  final String filename;

  public TextFile(String filename) {
    this.filename = filename;
  }

  // Это единственный метод интерфейса Iterable
  public Iterator<String> iterator() {
    return new TextFileIterator();
  }

  // Этот не статический класс является реализацией итератора
  class TextFileIterator implements Iterator<String> {

    // Поток для чтения
    BufferedReader in;

    // Возвращает значение следующего вызова next()
    String nextline;

    public TextFileIterator() {
      // Открыть файл, прочитать и запомнить первую строку
      //   Выбрать строку наперед для использования функции hasNext()
      try {
        in = new BufferedReader(new FileReader(filename));
        nextline = in.readLine();
      } catch (IOException e) {
        throw new IllegalArgumentException(e);
      }
    }

    // Если следующая строка не равна null, у нас есть следующая строка
    public boolean hasNext() {
      return nextline != null;
    }

    // Возвращает следующую строку, но сначала читает еще одну строку за ней
    public String next() {
      try {
        String result = nextline;

        // Если еще не достигли EOF ...
        if (nextline != null) {
          nextline = in.readLine();    // Читать еще одну строку
          if (nextline == null)
            in.close();                // Закрыть по достижению EOF
        }

        // Возвратить строку, прочитанную раннее
        return result;

      } catch (IOException e) {
        throw new IllegalArgumentException(e);
      }
    }

    // Файл только для чтения, мы не разрешаем удаление строк
    public void remove() {
      throw new UnsupportedOperationException();
    }
  }

  public static void main(String[] args) {
    String filename = "TextFile.java";
    if (args.length > 0)
      filename = args[0];

    for (String line : new TextFile(filename))
      System.out.println(line);
  }
}

Вопрос 1.

Для чего можно использовать реализацию интерфейса Iterable в создаваемых вами классах?

Вопрос 2.

Какие методы придется при этом реализовать?

Last updated