s.p
s.p

Reputation: 139

creating custom iterator with unit tests

I am learning programming and new to this domain as i am have a mechanical background. Yesterday I received a problem statement from prof. where he provided us an custom Iterator which is designed to iterate over given elements alternatively.

Alternate Iterator code is as following.

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

}

Now, The AlternatingIterator should alternate in order between the iterators it receives in its constructor. For example if constructed with three iterators [a,b,c], [1,2] and [x,y,z], the iterator should produce the elements in this order ‘a, 1, x, b, 2, y, c, z’

Also i have to Write unit tests for the ‘hasNext’ and ‘next’ methods.

Can we implement any other data structure than queue?

I am completely blown off and tired to understand how to solve this challenge but very confused here. If you guys can help me then i can learn important concept very quickly.

Thank you in advance and any help is appreciated.

Upvotes: 0

Views: 851

Answers (2)

scriber36
scriber36

Reputation: 135

Of course, we can use anything we can imagine. The following implementation alternates dynamically. Instead of using a queue, I store all the received iterators in an array:

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

}

But the same could be made statically using a queue, enqueuing all the elements from the iterators, having only that one queue as in your (your prof's) code.

@Andy Turner: Collecting the elements from the iterator results in not relying on the source collection the entire time until the last element is not obtained. Sure, from Java8 we use Streams, which won't gift us concurrent exceptions, but before Java8, buffering an/more iterator into a collection could have been safer in my opinion.

EDIT: you wrote then we can use the iterator of that given collection. Yeah, I totally forgot that, implementing an iterator for a simple queue is for sure pointless :)

Upvotes: 1

Andy Turner
Andy Turner

Reputation: 140299

A queue is helpful here, but not in the way you are using it.

There is no real point in copying all the elements from the iterators provided to the constructor into a queue, and then implementing a custom iterator from this queue: if you are going to put the elements into a collection which already implements Iterable, you may as well just use that Iterable's iterator.

But this is also probably not the point of the exercise: you can do this lazily with respect to consuming the input iterators. (Besides, what if one of the iterators is infinite...)

The idea I would suggest is to make a queue of iterators, not elements. Here is a description of how you could do it; I don't want to give you code to spoil your learning experience:

  • In your constructor, put the iterators from the parameter into a queue.
  • To implement hasNext(), pop iterators off the head of the queue for which hasNext() is false; stop when the iterator at the head of the queue has a next element (in which case return true), or the queue is empty (in which case return false).
  • To implement next(), pop the head iterator out of the queue, and get its next element: this is what you will return. But, before you do, if the iterator has more elements, push it onto the tail of the queue (doing this means that you will look at the next iterator on the next iteration).

Upvotes: 1

Related Questions