создание собственного итератора с юнит-тестами - PullRequest
0 голосов
/ 13 октября 2018

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

Альтернативный код итератора выглядит следующим образом.

import java.util.Iterator;

import java.util.LinkedList;

import java.util.Queue;

public class AlternatingIterator<E> implements Iterator{

private final Queue<E> queue = new LinkedList<>();

public AlternatingIterator(Iterator<E> ... iterators) {
    for(Iterator<E> iterator : iterators) {
        while(iterator.hasNext())
            queue.add(iterator.next());
    }
}

@Override
public boolean hasNext() {
    return queue.isEmpty() ? false : true;
}

@Override
public Object next() {
    return queue.poll();
}

}

Теперь AlternatingIterator должен чередоваться по порядку между итераторами.он получает в своем конструкторе.Например, если построено с тремя итераторами [a, b, c], [1,2] и [x, y, z], итератор должен создавать элементы в следующем порядке: a, 1, x, b, 2, y, c, z '

Также мне нужно написать модульные тесты для методов hasNext и next.

Можем ли мы реализовать любую другую структуру данных, кроме очереди?

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

Заранее спасибо, и любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

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

import java.util.Iterator;

/**Alternates on the given iterators.*/
public class AlternatingIterator<E> implements Iterator {

    /**Stores the iterators which are to be alternated on.*/
    private Iterator<E>[] iterators;

    /**The index of iterator, which has the next element.*/
    private int nextIterator = 0;

    /**Initializes a new AlternatingIterator object.
     * Stores the iterators in the iterators field.
     * Finds the first iterator with an available element.*/
    public AlternatingIterator(Iterator<E> ... iterators) {
        this.iterators = iterators;

        if (!iterators[0].hasNext())
            findNextIterator();
    }

    @Override
    public boolean hasNext() {
        return iterators[nextIterator].hasNext();
    }

    @Override
    public Object next() {
        E element = iterators[nextIterator].next();

        findNextIterator();

        return element;
    }

    /**Steps on iterators, until one has next element.
     * It does not step on them infinitely, stops when
     * the lastly used iterator is reached.*/
    private void findNextIterator() {
        int currentIterator = nextIterator;

        // Finding iterator with element remaining.
        do {
            stepNextIterator();
        } while (!iterators[nextIterator].hasNext() && nextIterator != currentIterator);
        // If it gets around to the same iterator, then there is no iterator with element.
    }

    /**Increases the nextIterator value without indexing out of bounds.*/
    private void stepNextIterator() {
        nextIterator = (nextIterator + 1) % iterators.length;
    }

}

Но то же самое можно сделать статически, используя очередь, ставя в очередь все элементы из итераторов, имея только эту одну очередь в качествев коде вашего (вашего профессора).

@ Энди Тернер: Сбор элементов из итератора приводит к тому, что он не полагается на исходную коллекцию все время, пока не будет получен последний элемент.Конечно, из Java8 мы используем Stream s, что не даст нам одновременных исключений, но до Java8 буферизация / более итератора в коллекцию могла бы быть более безопасной, на мой взгляд.

EDIT: вы написали, что мы можем использовать итератор этой заданной коллекции.Да, я совершенно забыл, что реализация итератора для простой очереди, безусловно, бессмысленна:)

0 голосов
/ 13 октября 2018

Очередь здесь полезна, но не так, как вы ее используете.

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

Но это также, вероятно, несмысл упражнения: вы можете сделать это лениво в отношении использования входных итераторов.(Кроме того, что, если один из итераторов бесконечен ...)

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

  • В конструкторе поместите итераторы из параметра в очередь.
  • Для реализации hasNext(),выталкивать итераторы из заголовка очереди, для которой hasNext() равно false;остановка, когда итератор в начале очереди имеет следующий элемент (в этом случае возвращает значение true) или очередь пуста (в этом случае возвращает значение false).
  • Чтобы реализовать next(), вставьте заголовокитератор выходит из очереди и получает следующий элемент: это то, что вы вернете.Но перед тем, как сделать это, если итератор имеет больше элементов, поместите его в конец очереди (это означает, что вы увидите следующий итератор на следующей итерации).
...