1. Overview

In this tutorial, we’ll explore different ways of generating random numbers within a range.

2. Generating Random Numbers in a Range

2.1. Math.random

Math.random gives a random double value that is greater than or equal to 0.0 and less than 1.0.

Let’s use the Math.random method to generate a random number in a given range [min, max):

public int getRandomNumber(int min, int max) {
    return (int) ((Math.random() * (max - min)) + min);
}

Why does that work? Let’s look at what happens when Math.random returns 0.0, which is the lowest possible output:

0.0 * (max - min) + min => min

So, the lowest number we can get is min.

Since 1.0 is the exclusive upper bound of Math.random, this is what we get:

1.0 * (max - min) + min => max - min + min => max

Therefore, the exclusive upper bound of our method’s return is max.

In the next section, we’ll see this same pattern repeated with Random#nextInt.

2.2. java.util.Random.nextInt

We can also use an instance of java.util.Random to do the same.

Let’s make use of the java.util.Random.nextInt method to get a random number:

public int getRandomNumberUsingNextInt(int min, int max) {
    Random random = new Random();
    return random.nextInt(max - min) + min;
}

The min parameter (the origin) is inclusive, whereas the upper bound max is exclusive.

2.3. java.util.Random.ints

The java.util.Random.ints method returns an IntStream of random integers.

So, we can utilize the java.util.Random.ints method and return a random number:

public int getRandomNumberUsingInts(int min, int max) {
    Random random = new Random();
    return random.ints(min, max)
      .findFirst()
      .getAsInt();
}

Here as well, the specified origin min is inclusive, and max is exclusive.

3. Generating Random Numbers in a Range With Some Exclusions

We can also generate a random number within a specified range while excluding certain values.

3.1. Math.random()

Let’s use Math.random() to generate a random number within a specified range while excluding some values:

static int getRandomWithExclusionUsingMathRandom(int min, int max, int [] exclude) {
    Arrays.sort(exclude);
    int random = min + (int) ((max - min + 1 - exclude.length) * Math.random());
    for (int ex : exclude) {
        if (random < ex) {
            break;
        }
        random++;
    }
    return random;
}

In the code above, we add an array of integers to the method argument.  The exclude array contains integer values that should be excluded from the random number generation.

Furthermore, we sort the array in ascending order to optimize the loop. By sorting the array, we ensure that once we’ve found an excluded number greater than the random number, we won’t find any more and break the loop early. If the array isn’t sorted, the loop might break prematurely.

Let’s take a moment to understand how the algorithm works to ensure that incremented random value isn’t in the exclude array. We can assume we have an array containing values we’re excluding and a random number:

int[] exclude = {2, 3, 5};
int random = 3;

Next, let’s iterate through the array and compare it with the random number:

for (int ex : exclude) {
    if (random < ex) {
        break;
    }
    random++;
}
return random;

Firstly, the algorithm begins by comparing the random value with the first element in the exclude array. Since the random value isn’t less than the first element in the array, the loop continues and increments the random number to 4.

Next, the loop then moves to the next element, which is 3. As the random number isn’t less than 3, the loop continues, incrementing the random number to 5.

Furthermore, the next value in the array is 5, which is equal to the random number. The loop increments the random number to 6 and then stops as we’ve reached the end of the array. Therefore, the returned random number is 6.

Notably, if the random value is less than any element in the array, the loop will break and return the current random value.

In the next section, we’ll use java.util.Random.nextInt() method to generate a random number within a specified range while excluding certain values, applying the same algorithm.

3.2. java.util.Random.nextInt()

In a previous section, we saw how to use java.util.Random.nextInt() to generate a random number within a specified range. Let’s broaden the method by implementing the functionality to exclude some numbers:

static int getRandomNumberWithExclusionUsingNextInt(int min, int max, int [] exclude) {
    Random rnd = new Random();
    Arrays.sort(exclude);
    int random = min + rnd.nextInt(max - min + 1 - exclude.length);
        for (int ex : exclude) {
            if (random < ex) {
                break;
            }
            random++;
        }
    return random;
}

Here, we create a new instance of Random and invoke the nextInt() method on it to generate a random number within a specific range with some exclusions.

3.3. java.util.Random.ints()

We can also generate a random number while excluding some values using the java.util.Random.ints() method:

int getRandomWithExclusion(int min, int max, int [] exclude) {
    Random rnd = new Random();
    OptionalInt random = rnd.ints(min, max + 1)
      .filter(num -> Arrays.stream(exclude).noneMatch(ex -> num == ex))
      .findFirst();
    return random.orElse(start);
}

The code above generates a stream of random integers within the specified range. We then use the filter() method of the Stream API to eliminate numbers in the exclude array.

Finally, we use the findFirst() method to get a number in the stream that’s not in the exclude array.

4. Conclusion

In this article, we saw alternative ways of generating random numbers within a range.

Code snippets, as always, can be found over on GitHub.