Introduction
In this tutorial, we'll take a look at how to generate random integers in a specific range in Java.
We'll be taking a look at several approaches, including core Java and third-party solutions:
- Random.ints()
- Random.nextInt()
- Math.random()
- SecureRandom.nextInt()
- ThreadLocalRandom.nextInt()
- SplittableRandom.ints()
Note: For each approach, we'll cover how to generate one random integer as well as how to generate a sequence of random integers.
All of these methods are lower-bound inclusive, and upper-bound exclusive.
Random.ints()
We're starting off with Random.ints()
which was added to the Random
class in Java 8, exactly for this purpose. Java originally didn't have a fully intuitive solution for this task, built-in.
The ints()
method returns a sequence of random values, in the form of an IntStream
. Being a Stream
implementation, it's unbounded:
Random random = new Random();
random.ints().forEach(System.out::println);
This results in:
-526320702
-744603161
474879020
1864311422
406782252
...
This is an unbounded IntStream
, which will generate any value from Integer.MIN_VALUE
to Integer.MAX_VALUE
. However, you can specify a range, as well as the number of elements you'd like to generate.
Additionally, the first argument is the number of elements you'd like to generate - otherwise, the stream will be generate an unlimited number of elements, until your Heap Memory space runs out:
List<Integer> intList = new Random().ints(5, 1, 11)
.boxed()
.collect(Collectors.toList());
System.out.println(intList);
Before collecting the IntStream
, we'll have to box it via the boxed()
method, which returns a stream consisting of the elements of the IntStream
, boxed to an Integer
. Then, we run collect()
on the returned stream - not the original one.
The collect()
method of the IntStream
doesn't return a collection - it runs a mutable reduction operation.
Running this code results in:
[1, 9, 9, 6, 2]
To generate a single random integer, you can simply tweak the first argument of the ints()
method, or use the findFirst()
and getAsInt()
methods to extract it from the IntStream
:
int randomInt = new Random().ints(1, 1, 11).findFirst().getAsInt();
System.out.println(randomInt);
This results in a random integer in the range between 1..10
(second argument is exclusive):
5
Random.nextInt()
A more classic example that you'll often see people using is simply utilizing the Random.nextInt()
method. It accepts a bound
parameter, which sets the upper bound, and sets the lower bound to 0
by default.
Unfortunately, it doesn't allow you to change this - so a quick and simple "hack" can be used to specify the boundaries:
int min = 10;
int max = 100;
System.out.println(new Random().nextInt(max - min) + min);
This results in a random integer in the range between min
and max
:
53
Generating a sequence of this would require us to call the method multiple times:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
Random random = new Random();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add(random.nextInt(upperBound - lowerBound) + lowerBound);
}
return result;
}
This is a List
-limited recreation of the Random.ints()
functionality, which simply returns a list of randomly generated integers in a range, with a given size:
List<Integer> integerList = intsInRange(5, 0, 10);
System.out.println(integerList);
Running this code would result in something along the lines of:
[3, 8, 2, 2, 9]
SecureRandom.nextInt()
The SecureRandom
class is an alternative to the classic Random
class, but provides a cryptographically strong random number generator. Random
internally relies on the system's clock to generate number seeds, which isn't truly random.
On the other hand, SecureRandom
takes much more random data from the environment to generate a much more random seed.
If cryptographic safety is a thing you're concerned with, you may opt to use SecureRandom
instead - which behaves in much the same way as Random
from the developer's point of view:
int max = 100;
int min = 10;
int randomInt = new SecureRandom().nextInt(max - min) + min;
System.out.println(randomInt);
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Which results in a random integer in the range between min
and max
:
95
And if you'd like to generate sequences, a helper method can be crafted:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
SecureRandom random = new SecureRandom();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add(random.nextInt(upperBound - lowerBound) + lowerBound);
}
return result;
}
Which you can use as:
List<Integer> integerList = intsInRange3(5, 0, 10);
System.out.println(integerList);
And which results in:
[0, 9, 5, 6, 5]
Math.random()
The Math
class provides us with great math-related helper methods. One of them is the Math.random()
method, which returns a random value between 0..1
. Typically, it's used to generate random percentile values.
However, in a similar vein to the Random.nextInt()
hack - you can utilize this functionality to generate any integer in a certain range:
int min = 10;
int max = 100;
int randomNumber = (int)(Math.random() * (max + 1 - min) + min);
System.out.println(randomNumber);
Though, this one is even less intuitive than the previous approach. Running this code results in something along the lines of:
43
If you'd like to work with a sequence, we'd create a helper method to append each generated value to a list:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add((int)(Math.random() * (upperBound + 1 - lowerBound) + lowerBound));
}
return result;
}
And then we can call it as:
List<Integer> integerList = intsInRange(5, 0, 10);
System.out.println(integerList);
Which produces:
[9, 0, 3, 2, 0]
ThreadLocalRandom.nextInt()
If you're working in a multi-threaded environment, the ThreadLocalRandom
class is meant to be used as a thread-safe equivalent to Random
. Fortunately, it does offer a nextInt()
method with both an upper and lower bound:
int randomInt = ThreadLocalRandom.current().nextInt(0, 10);
System.out.println(randomInt);
As usual, the lower bound is included, while the upper bound isn't:
3
Similarly, you can create a helper function to generate a sequence of these:
public static List<Integer> intsInRange(int size, int lowerBound, int upperBound) {
List<Integer> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
result.add(ThreadLocalRandom.current().nextInt(lowerBound, upperBound));
}
return result;
}
Which you can use as:
List<Integer> integerList = intsInRange4(5, 0, 10);
System.out.println(integerList);
[1, 9, 1, 9, 7]
SplittableRandom.ints()
A less-known class in the Java API is the SplittableRandom
class - which is used as a generator of pseudo-random values. As the name implies, it's splittable and runs in parallel, and is really only used when you have tasks that could split again into smaller sub-tasks.
It's worth noting that this class is also based on non-secure seed generation - if you're looking for a safe seed generation, use SecureRandom
.
The class offers an ints()
method, which from our perspective, works in the same way as Random.ints()
:
List<Integer> intList = new SplittableRandom().ints(5, 1, 11)
.boxed()
.collect(Collectors.toList());
System.out.println(intList);
Which results in:
[3, 2, 8, 10, 3]
And, if you'd like to generate only one random number, you can ditch the collector and use findFirst()
with getAsInt()
:
int randomInt = new SplittableRandom().ints(1, 1, 11).findFirst().getAsInt();
System.out.println(randomInt);
Which results in:
4
Conclusion
In this tutorial, we've taken an exhaustive look at how to generate random integers in range in Java.
We've gone over the newest and most useful method, as well as some other popular methods of finishing this task. Most of the approaches rely on the Random
or Random
-equivalent classes, used for more specific contexts.