StreamableGenerator can return streams of RandomGenerator objects SplitableGenerator can return a new generator from this one (spit itself) JumpableGenerator can jump ahead a moderate number of draws LeapableGenerator can jump ahead a large number of draws ArbitrarilyJumpableGenerator can jump ahead an arbitrary number of draws Getting the default RandomGenerator can be done as follows (this is the simplest approach to start generating pseudo-random numbers but you have no control over what is chosen):

RandomGenerator defaultGenerator
  = RandomGenerator.getDefault();
// start generating pseudo-random numbers
defaultGenerator.nextInt/Float/…();
defaultGenerator.ints/doubles/…();

Besides these interfaces, the new API comes with a class (RandomGeneratorFactory) which is a factory of pseudo-random generators based on the selected algorithms. There are three groups of new algorithms (most probably, more are on the way) as follows:

LXM group

  • L128X1024MixRandom
  • L128X128MixRandom
  • L128X256MixRandom
  • L32X64MixRandom
  • L64X1024MixRandom
  • L64X128MixRandom
  • L64X128StarStarRandom
  • L64X256MixRandom

Xoroshiro group

  • Xoroshiro128PlusPlus

Xoshiro group

  • Xoshiro256PlusPlus

The highlighted algorithm is the default one (L32X64MixRandom).Depending on the pseudo-random generator type we can select all/some of the previous algorithms. For instance, the L128X256MixRandom algorithm can be used with SplittableGenerator but it cannot be used with LeapableGenerator. A mismatch between the chosen algorithm and the pseudo-random generator results in IllegalArgumentException. The following figure can help you to decide which algorithm to use.

Figure 1.28 – JDK 17 random generator’s algorithm and their properties

This figure was produced via the following code meant to list all available algorithms and their properties (streamable, leapable, statistical, and so on):

Stream<RandomGeneratorFactory<RandomGenerator>> all
     = RandomGeneratorFactory.all();
Object[][] data = all.sorted(Comparator.comparing(
                   RandomGeneratorFactory::group))
  .map(f -> {
     Object[] obj = new Object[]{
       f.name(),
       f.group(),
       f.isArbitrarilyJumpable(),
       f.isDeprecated(),
       f.isHardware(),
       f.isJumpable(),
       f.isLeapable(),
       f.isSplittable(),
       f.isStatistical(),
       f.isStochastic(),
       f.isStreamable()
     };
     return obj;
  }).toArray(Object[][]::new);

Choosing an algorithm can be easily done by name or properties.

Choosing an algorithm by name

Choosing an algorithm by name can be done via a set of static of() methods. There is an of() method in RandomGenerator and in RandomGeneratorFactory that can be used to create a pseudo-random generator for a specific algorithm as follows:

RandomGenerator generator
  = RandomGenerator.of(“L128X256MixRandom”);
RandomGenerator generator
  = RandomGeneratorFactory.of(“Xoroshiro128PlusPlus”)
                          .create();      

Next, we can generate pseudo-random numbers by calling the well-known API (ints(), doubles(), nextInt(), nextFloat(), and so on).If we need a certain pseudo-random generator and algorithm then we can use the of() method of that generator as follows (here, we create a LeapableGenerator):

LeapableGenerator leapableGenerator
  = LeapableGenerator.of(“Xoshiro256PlusPlus”);
LeapableGenerator leapableGenerator = RandomGeneratorFactory
  .<LeapableGenerator>of(“Xoshiro256PlusPlus”).create();

In the case of SplittableRandom, you can use the constructor as well but you cannot specify the algorithm:

SplittableRandom splittableGenerator = new SplittableRandom();

In the bundled code, you can see more examples.

Choosing an algorithm by property

As you saw in figure 1.28, an algorithm has a set of properties (is jumpable, is statistical, and so on). Let’s pick up an algorithm that is statistical and leapable:

RandomGenerator generator = RandomGeneratorFactory.all()
  .filter(RandomGeneratorFactory::isLeapable)
  .filter(RandomGeneratorFactory::isStatistical)
  .findFirst()
  .map(RandomGeneratorFactory::create)
  .orElseThrow(() -> new RuntimeException(
       “Cannot find this kind of generator”));             

The returned algorithm can be Xoshiro256PlusPlus.

Leave a Reply

Your email address will not be published. Required fields are marked *