Решение: Итератор, который не знает, есть ли у него следующий элемент - PullRequest
0 голосов
/ 01 апреля 2020

Я написал итератор, который возвращает подграфы фиксированного размера другого заданного неориентированного простого графа. Он поддерживает внутренний граф, который является в настоящее время вычисляемым подграфом и имеет частные стеки и списки, из которых он вычисляет следующий подграф.

Невозможно узнать, может ли итератор вернуть другой элемент, потому что, возможно, алгоритм завершает работу при попытке найти следующий подграф.

В этом варианте шаблон next() и hasNext(), который Java предлагает, не работает. В настоящее время я написал свой собственный интерфейс BlindIterator со следующими абстрактными методами:

 /**
 * @return True iff the current element is a valid return.
 */
public boolean hasCurrent();

/**
 * @return Returns the current element, but does NOT generate the next element. This method can be called


 * as often as wanted, without any side-effects.
 */
public T getCurrent();

/**Generates the next element, which can then be retrieved with getCurrent(). This method thus only provides
 * this side-effect. If it is called while the current element is invalid, it may produce and exception,
 * depending on the implementation on the iterator.
 */
public void generateNext();

Является ли это распространенным шаблоном и существуют ли лучшие проекты, чем мой?

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Вы реализуете итератор для предварительной загрузки / кэширования следующего элемента (подграфа).

Например, если ваши элементы получены из Supplier, где единственным методом является get() метод, который возвращает следующий элемент, или null, если больше нет доступных элементов, вы бы реализовали Iterator следующим образом:

public final class SupplierIterator<E> implements Iterator<E> {

    private final Supplier<E> supplier;
    private E next;

    SupplierIterator(Supplier<E> supplier) {
        this.supplier = supplier;
        this.next = supplier.get(); // cache first (preload)
    }

    @Override
    public boolean hasNext() {
        return (this.next != null);
    }

    @Override
    public E next() {
        if (this.next == null)
            throw new NoSuchElementException();
        E elem = this.next;
        this.next = supplier.get(); // cache next
        return elem;
    }
}

Answer by Joni имеет хорошую реализацию Iterator, в которой вы можете использовать BlindIterator в качестве источника элементов.

Поскольку вы только изобрели BlindIterator to Обойти ваши предполагаемые ограничения Iterator, я бы рекомендовал не делать этого. Сделайте так, чтобы реализация итератора вызывала лежащие в основе логики «create» c напрямую.

1 голос
/ 01 апреля 2020

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

    class BlindIteratorIterator<T> implements Iterator<T> {

        private BlindIterator<T> iterator;

        public BlindIteratorIterator(BlindIterator<T> iterator) {
            this.iterator = iterator;
            iterator.generateNext();
        }

        @Override
        public boolean hasNext() {
            return iterator.hasCurrent();
        }

        @Override
        public T next() {
            T next = iterator.getCurrent();
            iterator.generateNext();
            return next;
        }
    }
...