Stop Newing a Random - Introducing Java's Improved RandomGenerator
4 min read1. Introduction
Randomness plays a critical role in various aspects of computer programming, from gaming and simulations, to cryptography and statistical analysis, and so forth.
Java has always provided ways to generate random numbers, such as the java.util.Random class. On top of that, with the introduction of the RandomGenerator interface in Java 17, the language takes a significant step forward in improving the efficiency and flexibility of random number generation.
In this blog post, we'll explore the new RandomGenerator interface, examine its real-world applications, compare it to prior Java versions, and draw conclusions about its potential impact.
2. Real-world application
Consider a simple lottery application that randomly selects a set of non-repeating numbers within a specified range. Here's an example using the new RandomGenerator interface:
import java.util.stream.Collectors;
import java.util.Set;
import java.util.Random;
import jdk.random.RandomGenerator;
import jdk.random.RandomGeneratorFactory;
public class Lottery {
public static void main(String[] args) {
RandomGeneratorFactory<RandomGenerator> factory = RandomGeneratorFactory.of("L64X128MixRandom");
RandomGenerator rng = factory.create();
int lowerBound = 1;
int upperBound = 50;
int numPicks = 6;
Set<Integer> winningNumbers = rng.ints(lowerBound, upperBound + 1)
.distinct()
.limit(numPicks)
.boxed()
.collect(Collectors.toSet());
System.out.println("Winning numbers: " + winningNumbers);
}
}
3. "Good old" days
Before the introduction of RandomGenerator, the most common approach to generating random numbers in Java was using the java.util.Random or java.util.concurrent.ThreadLocalRandom classes. Here's the lottery application example implemented using java.util.Random:
import java.util.stream.Collectors;
import java.util.Set;
import java.util.Random;
public class Lottery {
public static void main(String[] args) {
Random random = new Random();
int lowerBound = 1;
int upperBound = 50;
int numPicks = 6;
//...
}
}
Now I just have to say, please don't use this anymore!
4. Why use RandomGenerator?
While the code differences between the two examples may appear subtle, the underlying improvements offered by RandomGenerator are significant:
- Algorithm Selection: The new RandomGenerator interface allows developers to choose from a variety of random number generation algorithms, offering improved performance and quality tailored to specific use cases.
- Factory Pattern: The RandomGeneratorFactory class provides a clean way to create instances of RandomGenerator, making it easier to switch between algorithms without modifying the code extensively.
- Stream API Integration: The RandomGenerator interface seamlessly integrates with Java's Stream API, simplifying the process of generating random numbers and enabling a more functional programming style.
5. One more thing
The RandomGenerator interface in Java 17 provides access to several high-quality random number generation algorithms that offer good performance and follow best practices. Some of these well-known algorithms include:
L64X128MixRandom
: This is a 64-bit generator with a 128-bit state, designed to have a fast mixing of its state. It is suitable for most applications that require a good balance between performance and quality.L128X256MixRandom
: This is a 128-bit generator with a 256-bit state, providing a stronger mixing of its state and improved statistical properties. It is suitable for applications that require higher-quality random numbers or larger state sizes, such as simulations or machine learning algorithms.Xoroshiro128Plus
: This is a 128-bit generator with a 128-bit state, based on xorshift operations and a rotation. It offers good performance and quality while being relatively simple to implement. However, it might not be suitable for applications that require high-quality random numbers with an extremely long period.Xoshiro256Plus
: This is a 256-bit generator with a 256-bit state, based on xorshift operations and a rotation. It provides better quality random numbers than Xoroshiro128Plus while maintaining good performance. This generator is suitable for a wide range of applications, including simulations, gaming, and cryptography.SplittableRandom
: This generator is specifically designed for concurrent usage in parallel algorithms. It allows for efficient splitting of its state, enabling the creation of new random number generators for use in separate threads. This is particularly useful in applications that require high-performance parallel random number generation.
When using the RandomGeneratorFactory class, you can create instances of these algorithms by specifying their names, like this:
RandomGeneratorFactory<RandomGenerator> factory = RandomGeneratorFactory.of("L64X128MixRandom");
RandomGenerator rng = factory.create();
And, the power is in your hands!
6. Conclusion
Java 17's improved RandomGenerator interface provides developers with a powerful, flexible, and efficient way to generate random numbers for various applications.
By offering a choice of algorithms and better integration with the Stream API, RandomGenerator significantly enhances the random number generation capabilities in Java compared to prior versions. Give it a try!