Java - Generate Random Range of Specific Numbers Without Duplication of Those Numbers - How To

Creating random numbers with no duplicates

The simplest way would be to create a list of the possible numbers (1..20 or whatever) and then shuffle them with Collections.shuffle. Then just take however many elements you want. This is great if your range is equal to the number of elements you need in the end (e.g. for shuffling a deck of cards).

That doesn't work so well if you want (say) 10 random elements in the range 1..10,000 - you'd end up doing a lot of work unnecessarily. At that point, it's probably better to keep a set of values you've generated so far, and just keep generating numbers in a loop until the next one isn't already present:

if (max < numbersNeeded)
{
throw new IllegalArgumentException("Can't ask for more numbers than are available");
}
Random rng = new Random(); // Ideally just create one instance globally
// Note: use LinkedHashSet to maintain insertion order
Set<Integer> generated = new LinkedHashSet<Integer>();
while (generated.size() < numbersNeeded)
{
Integer next = rng.nextInt(max) + 1;
// As we're adding to a set, this will automatically do a containment check
generated.add(next);
}

Be careful with the set choice though - I've very deliberately used LinkedHashSet as it maintains insertion order, which we care about here.

Yet another option is to always make progress, by reducing the range each time and compensating for existing values. So for example, suppose you wanted 3 values in the range 0..9. On the first iteration you'd generate any number in the range 0..9 - let's say you generate a 4.

On the second iteration you'd then generate a number in the range 0..8. If the generated number is less than 4, you'd keep it as is... otherwise you add one to it. That gets you a result range of 0..9 without 4. Suppose we get 7 that way.

On the third iteration you'd generate a number in the range 0..7. If the generated number is less than 4, you'd keep it as is. If it's 4 or 5, you'd add one. If it's 6 or 7, you'd add two. That way the result range is 0..9 without 4 or 6.

Java - generate Random range of specific numbers without duplication of those numbers - how to?

You can fill an array with all values from 1 to 12 and then shuffle them (see e.g. Why does Collections.shuffle() fail for my array?)

Random number generator without duplication

Create a List, and populate it with the elements in your range. Then shuffle() the list, and the order is your random numbers. That is, the 0-th element is your first random number, the 1st element is your second random number, etc.

Java generating non-repeating random numbers

Integer[] arr = {...};
Collections.shuffle(Arrays.asList(arr));

For example:

public static void main(String[] args) {
Integer[] arr = new Integer[1000];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
Collections.shuffle(Arrays.asList(arr));
System.out.println(Arrays.toString(arr));

}

Printing Non Repeating Random Numbers within a range

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


Related Topics



Leave a reply



Submit