Rob Williams is a probabilistic Lean coder of Java and Objective-C. Rob is a DZone MVB and is not an employee of DZone and has posted 170 posts at DZone. You can read more from them at their website. View Full User Profile

Making Mock Data Circular

06.25.2009
| 4330 views |
  • submit to reddit

Was writing a test today where I was doing a Command Pattern that would allow me to contain a set of repeated invocations in a timebox. In other words: call me as many times as possible in x milliseconds. So for the test, I was using random #s, but that kept going to zero after a ton of invocations. Got out my Distribution class that allows me to say 'give me random #s with x% in range between y and z.' Once I do that, though, I have to know how many #s I am going to need, and I don't really.

First, I did the usual TDD thing: write it and let it fail. Sure enough, it fails on .next() after the iterator is exhausted. Did some searches on whether there is a reset method on some specialized iterator. But then, I decided it would just make more sense to make a simple CircularIterator, like so:

/**
* Provides the ability to give a fixed sample, and this class will provide an
* {@link Iterator} that will just repeatedly loop through the collection.
*
* @author Rob
*
* @param
* @Pattern Decorator
*
*/
public class CircularIterator implements Iterator {

/**
* Just using a real iterator here, after running through the set each time.
*/
private Iterator i;

/**
* The sample we want to cycle through.
*/
private Collection collection;

public CircularIterator(Collection collection) {
this.collection = collection;
this.i = collection.iterator();
}

/**
* Will always return true, since we are just looping.
*/
public boolean hasNext() {
return i.hasNext();
}

/**
* Gets the next element. If there are no more, the iterator {@link #i} is
* recreated.
*/
public T next() {
if (!i.hasNext())
i = collection.iterator();
return i.next();
}

/**
* Just proxies call so should work as usual.
*/
public void remove() {
i.remove();
}

}

 

Of course, this means that you are going to just get the same #s over and over again, but in a lot of cases (like mine), that doesn't really matter: scores, confidence levels, donations, whatever.

This is a good example of the Decorator pattern: it implements the interface, holds an instance of the type it's extending, and proxies on the methods it doesn't need to change. The nice part is that I can just create this, using the same declarations and then call next() for as long as I like.

From http://www.jroller.com/robwilliams

Published at DZone with permission of Rob Williams, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Felix Martin replied on Thu, 2009/06/25 - 2:36am

As you usually iterate over iterators in this way:

while (it.hasNext()) {
it.next();
}

 And the iterator index is moved when you call the next() method, your code should be:

public E next() {
E element = i.next();
if (!i.hasNext()) {
i = collection.iterator();
}
return element;
}

 Besides there is another problem with the remove method if you want to remove the last element of the iterator, you will get an IllegalStateException. The complete class right code should be:

 

package collections;

import java.util.Collection;
import java.util.Iterator;

/**
*
* @author fmartin
*
* @param <E>
*/
public class CircularIteratorMod<E> implements Iterator<E> {

/**
* Just using a real iterator here, after running through the set each time.
*/
private Iterator<E> i;

/**
* The sample we want to cycle through.
*/
private Collection<E> collection;

public CircularIteratorMod(Collection<E> collection) {
this.collection = collection;
this.i = collection.iterator();
}

/**
* Will always return true, since we are just looping.
*/
public boolean hasNext() {
if (!i.hasNext()) {
i = collection.iterator();
}
return true;
}

/**
* Gets the next element.
*/
public E next() {
return i.next();

}

/**
* Just proxies call so should work as usual.
*/
public void remove() {
i.remove();
}

}

 

 

 

 

 

Gerrit Cap replied on Thu, 2009/06/25 - 3:48am

None of the code above does work, if one would use an iterator that behaves circular, what is the point of calling hasNext() everytime ? Just imagine code that doesn't call hasNext() -- even if that would be bad practice -- and only calls next().

The hasNext() method should just return true by default unless the collection is empty that is. The next method on the other hand should check if the underlying iterator has any next elements, if not then re-instantiate it. Unless the collection is empty then it should throw a NoSuchElementException.

 

Although at first it seems to be a nice example of trying to apply the Decorator pattern the result by doing so will be very difficult to withstand any unit test on Iterator behaviour.

 

Gerrit

 

sub online replied on Fri, 2009/06/26 - 1:28am

no need to discuss!(no need for discussion.).riff raff! these people give me the creeps. riff raff.That company wasted too much time fighting its own.Tiffany JewelleryThat's rubbish! It's no like that at all. That's rubbish.links of londonSaved by the bell.links of londonHow would I know!You scared me.Don't bother.I have no choice.What now!Why torture yourself!Don't you have a heart!

Reinhard Nägele replied on Fri, 2009/06/26 - 1:28am

No need to roll your own. Look at the Iterators class in Google Collections. They do it the right way.

Rob Williams replied on Tue, 2009/07/07 - 7:35pm

lol.. guys, it works for what it was intended/needed for.. if I need it for something else, I will worry about the horrors of, say, emptying the thing and getting a nosuchelement exception then..

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.