Alternatives to java.util.Random
As discussed in our Java random numbers introduction, the JDK provides a number of
different random number generators. In particular, it provides some alternatives to the "raw" java.util.Random
class, which prior to Java 8 was the standard class to use for random number generation in Java.
Random number generators provided by the Java platform
Out of the box, Java provides the following alternatives:
- ThreadLocalRandom is a fast, medium-quality random number generator
with a period of 264 that passes many statistical tests (but whose algorithm isn't fixed in principle
and could change in future Java versions);
- SecureRandom is a slow but cryptographic-strength algorithm that should be
used in security-based applications such as for generating random encryption keys;
- SplittableRandom is for use in divide-and-conquer algorithms
where a large number of instances need to be combined, e.g. where each node of a search tree might have its
own instance— in particular, it was designed to be compatible with the Java Stream API.
Other random number generation techniques
Despite these options, you may have recourse to implement a specific RNG algorithm yourself. On the remainder of this page, we will
mention some different options.
XORShift
The XORShift generator provides fast, medium-quality random number generation that
is useful as a quick-and-dirty method of generating random numbers "inline". It can generate a 64-bit number with just
three bitshifts and 3 XOR operations and requires only one long value. As an actual implementation of
Random, it is less useful since the addition of ThreadLocalRandom to the Java
platform,
unless you need a deterministic generator that starts at a specified seed and are willing to trade
off a degree of statistical performance.
In applications where you need good— but not cryptographic— quality
random numbers and need to generate a large number of them, then a Java
implementation of the Numerical Recipes random number
generator is often a reasonable choice. This is within the same order of magnitude
of the speed of java.util.Random and generates numbers of a much higher quality.
However, it still does not generate numbers of cryptographic quality (see
the next section).
Random numbers if you're fussy about quality but not CPU usage
If you need high-quality random numbers "out of the box", for example for
generating a random encryption key
or for cases where you want to overcome
some of the weaknesses of java.util.Random,
then you can generally use java.security.SecureRandom
as a drop-in replacement for java.util.Random:
Random diceRoller = new SecureRandom();
// proceed as before...
The SecureRandom implementation provides a much higher quality of
randomness, and, with help from the OS, seeds itself using sources of
entropy (or "true unpredictability") available
on the local machine. However, it is about 20-30 times slower than other typical generators.
(Note that "slower" still means you can produce about a million random longs
in a second on a 2GHz processor!)
Subclassing java.util.Random
We should iterate that it is essentially the underlying algorithm of java.util.Random that we want to replace. The class itself still provides various
useful methods, such as being able to take an arbitrary generator and from it produce
random numbers with a normal distribution, useful for
simulations.
This essentially means that, whatever technique we choose, we usually want to
subclass java.util.Random, overriding its
bit generation method but essentially nothing else.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.