Using java.util.Random
In our introduction to random numbers in Java, we saw a brief example
of generating random integers with the java.util.Random class. On this page, we'll look
in a little more detail at how this class works. This will give us some guidance on how to use
it most effectively, and when not to use it.
Tips for using java.lang.Random
First, some practical advice. If you don't want to get too theoretical, and you just
want a casual random number generator, e.g. for a dice roll or the starting position of
a baddy in your next blockbuster game, then java.lang.Random is still OK for that
kind of use if you at least make the most of the class:
-
Use the most appropriate method provided by the Random
class. The library implementers understand the limitations of the method used by java.lang.Random,
and have
at least provided methods to get round them as much as possible. For example, if you
need a random bit, always use nextBoolean(); don't invent an ad-hoc solution,
such as taking nextInt() and ANDing with 1. For subtle reasons, this will
produce less random results.
-
Similarly, don't use the following "idiom":
// This is WRONG -- don't do this!!
int no = Math.abs(r.nextInt()) % n;
If you do this, then depending on n, you will either bias your results or not
make them as random as they could be. If you need an integer between 0 and some upper bound, use
the corresponding method
provided by the Random class rather than inventing some other, incorrect
solution.
-
Avoid using the class for tests based on a power of two—
especially a low power of two— such as the following1:
if (r.nextInt() >= 4) {
...
}
and especially especially where you mask off some number of low bits and then test:
if ((r.nextInt() & 0x7fff) >= 4) {
...
}
It's easy for this kind of situation to crop up accidentally when using java.lang.Random
to generate test data, and can mean your "test" executes different or biased code paths compared to "real"
situations. To understand why this kind of use of Random isn't very good,
see the section on the randomness of bit positions.
-
Never use java.lang.Random for "serious" use, such
as scientific experiments, generating session IDs on a web server,
or gambling programs where money is involved.
-
If possible, avoid using java.lang.Random for choosing "groups of numbers"
(e.g. 3D coordinates) or "groups of random items" (e.g. random strings of a certain length):
the method used has serious limitations on the range and randomness of
combinations it can generate.
Next: how does java.lang.Random work, and how good is it?
If you want to understand the above issues in more detail,
then the next section deals with the "Java Random algorithm",
looking at how java.lang.Random works and some of its limitations.
You should also look at the section on alternatives
to java.util.Random, which looks at various random number generators that you could use
as a higher-quality replacement. In particular, you should look at:
- the XORShift generator, which provides a low-cost random
number generation technique that avoids many of the problems of java.util.Random;
- the SecureRandom class, for cases where you need
a cryptography-quality random number generator (in general, where security depends
on the quality and unpredictability of the random numbers you generate);
- the Numerical Recipes algorithm, which often
provides a good compromise between speed and quality of generation.
1. Just to be clear: the simple test of >= effectively first tests if the number
is positive or negative. That part will be reasonably random). Then in the case of
the number being positive, the expression tests if bit 2 is set. This latter stage will introduce
a high element of non-randomness.