1

I am trying to write a simple random number generator class that will print non duplicate numbers within a given range of max and min. I have the logic all down and I am using a set as well however I still get some repeating numbers. The idea is that if I declare min and max to be 0 and 5 I should get random numbers like 2 3 1 5 4 0. Then it can reset and give me the numbers again randomly within the range without repetition. See code below

package RandomNumberGen;

import java.util.*;
public class RandomNumberGenerator {

Random random = new Random();
int minimum;
int maximum;

Set<Integer> hSet = new HashSet<>(range);

public RandomNumberGenerator(int min, int max)
{
    minimum =  min;
    maximum = max;
}

public void generateRandomNumbers()
{
    int range =  maximum - minimum + 1; 
    int randomValue = 0; 

    if(shouldReset())
    {
        hSet.clear();
    }

    do
    {
        randomValue =  minimum + random.nextInt(range); 
    } while(!hSet.add(randomValue));

    System.out.println("The next random number is: " + randomValue);  

}

public boolean shouldReset()
{
    return hSet.size() >= maximum - minimum + 1;
}


public static void main(String[] args) 
{
    RandomNumberGenerator rng = new RandomNumberGenerator(1,10);
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();

    System.out.println("Should restart now");

    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
    rng.generateRandomNumbers();
}

}

Currently in my output I am getting this despite using a HashSet to remove non repeating integers: I am expecting something like 10 8 7 5 9 6 but instead I get

The next random number is: 9

The next random number is: 6

The next random number is: 8

The next random number is: 9

The next random number is: 6

The next random number is: 8

user6952090
  • 65
  • 1
  • 8

2 Answers2

1

Currently, your set does nothing to prevent duplicates. You should have declared your set as a field, instead of a local variable. The set essentially keeps track of which numbers have been generated.

public class RandomNumberGenerator {

    private int minimum;
    private int maximum;
    private Random random = new Random();
    private Set<Integer> hSet =  new HashSet<>();

    public RandomNumberGenerator(int min, int max)
    {
        minimum = min;
        maximum = max;
    }

    public void printRandomNumber()
    {
        int range =  maximum - minimum + 1; 
        int randomValue = 0; 

        do
        {
            randomValue =  minimum + random.nextInt(maximum - minimum + 1); 
        } while(!hSet.add(randomValue));

        System.out.println("The next random number is: " + randomValue);    
    }
}

You should also add a method call shouldReset to indicate whether all the numbers are generated:

public boolean shouldReset() {
    return hSet.size() >= maximum - minimum + 1; 
}

and a reset method:

public void reset() {
    hSet.clear();
}

Another way to do this is to shuffle a list of all the available numbers, and return the elements of the shuffled list sequentially:

public class RandomNumberGenerator {

    private int minimum;
    private int maximum;
    private Iterator<Integer> iter;

    public RandomNumberGenerator(int min, int max) {
        minimum = min;
        maximum = max;
        reset();
    }

    public void printRandomNumber() {

        System.out.println("The next random number is: " + iter.next());
    }

    public boolean shouldReset() {
        return !iter.hasNext();
    }

    public void reset() {
        List<Integer> list = new ArrayList<>(IntStream.rangeClosed(min, max).boxed().collect(Collectors.toList()));
        Collections.shuffle(list);
        iter = list.iterator();
    }
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • I'd just use the returned boolean of `Set::add` in the condition of the loop. `while(!hSet.add(randomValue))` – UninformedUser Aug 11 '19 at 03:14
  • 1
    @AKSW Edited. Personally I find that a little less readable, but maybe that's just me. – Sweeper Aug 11 '19 at 03:17
  • Well, yeah - no need to edit, as you said, it's just a matter of taste I guess. And the use case here is most likely not HPC oriented. And I'd either go with your shuffle solution (sufficient enough here) or for more advanced stuff would use Apache Commons Math resp. Apache RNG lib for creating random numbers etc. – UninformedUser Aug 11 '19 at 03:33
  • @Sweeper thanks a lot because this prints out random non repeating integers. I want this printRandomNumber method to keep generating numbers once everything in range happens. So will I put the shouldReset boolean check after the while loop in the printRandom method? – user6952090 Aug 11 '19 at 04:47
  • @user6952090 You should add another method called `reset`. And at the _start_ of `printRandomNumber`, check `shouldReset`, and if it is true, call `reset`. – Sweeper Aug 11 '19 at 04:51
  • @Sweeper thanks yet again! That suggestion fixed all the issues. See corrected code above. I didn't bother creating a reset method after all, just did a clear on the hashSet if shouldReset was true at start of printRandomMethod – user6952090 Aug 11 '19 at 18:28
0

Since Set<Integer> hSet = new HashSet<>(); is declared locally within the printRandomNumber function it is recreated every time this function is called, so it never tracks what was stored previously.

If you want it to persist throughout all the calls to printRandomNumber you could make it a global variable instead.

AbsoluteSpace
  • 710
  • 2
  • 11
  • 21