import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Random; public class DataProvider implements Iterable { /** * By default the numbers will be in the range 1--2047 */ private final int RANGE_DEFAULT = 2047; /** * By default, the odds of a negative number at 1 in 100 */ private final int ODDS_DEFAULT = 100; /** * A private, but the iterator actually gets returned outside the class * This works because the only methods used outside the class are those * in the iterator interface * * @author geoffreytowell * */ private class DataIterator implements Iterator { /** * A random number generator */ private Random random; /** * The number of Integers reamining to be generated */ int remaining; /** * The positive bound on the largest number */ int range; /** * The odds of a negative number */ int negOdds; protected DataIterator(int seed, int count, int rang, int nOdds) { random = new Random(seed); remaining = count; range = rang; negOdds = nOdds; } /** * @return true iff the generator has more numbers */ @Override public boolean hasNext() { return remaining>0; } /** * @return the next number in the sequence. */ @Override public Integer next() throws NoSuchElementException { if (remaining <=0) throw new NoSuchElementException("No more data available"); remaining--; int rtn = random.nextInt(range)+1; if (negOdds>0 && random.nextInt(negOdds)==(negOdds-1)) rtn = -rtn; return rtn; } } /** * Make an iterator with the existing parameters of the provider */ @Override public Iterator iterator() { return new DataIterator(seed, numberOfNumbers, range, negOdds); } /** * Seed for random number generator */ int seed; /** * Number of numbers for the iterator to return */ int numberOfNumbers; /** * The largest number to return */ int range; /** * The odds of a negative number */ int negOdds; /** * Create a data generator * * @param seed the random seed. Using the same seed will result in the same sequence of numbers * @param count the number of Integers for this generator to generate * @throws IllegalArgumentException */ public DataProvider(int seed, int count) throws IllegalArgumentException { if (count<=0) throw new IllegalArgumentException("Count must be greater than zero. Received: " + count); this.seed=seed; numberOfNumbers = count; range = RANGE_DEFAULT; negOdds = ODDS_DEFAULT; } void setRange(int r) { this.range=r; } /** * Create a data generator. * * @param seed the random seed as a string Using the same seed will result in the same sequence of numbers * @param count the number of Integers for this generator to generate (as a string) * @throws IllegalArgumentException * @throws NumberFormatException */ public DataProvider(String seed, String count) throws IllegalArgumentException, NumberFormatException { this(Integer.parseInt(seed), Integer.parseInt(count)); } /** * A sample driver for the class. When run from the command line, accepts 2 args, the seed * and the count * @param args */ public static void main(String[] args) { DataProvider provider=null; try { if (args.length>=2) provider = new DataProvider(args[0], args[1]); else provider = new DataProvider(100, 10); } catch (NumberFormatException nfe) { System.err.println(nfe.toString()); } catch (IllegalArgumentException iae) { System.err.println(iae.toString()); return; } int c=0; Iterator iter = provider.iterator(); while (iter.hasNext()) { System.out.println("A " + c++ + " " + iter.next()); } c=0; Iterator iter2 = provider.iterator(); while (iter2.hasNext()) { System.out.println("B " + c++ + " " + iter2.next()); } c=0; iter = provider.iterator(); iter2 = provider.iterator(); while (iter.hasNext() && iter2.hasNext()) { System.out.println("C " + c++ + " " + iter.next() + " " + iter2.next()); } } }