How do I use the RandomGenerator API introduced in JDK 17?

The RandomGenerator API, introduced in JDK 17, provides a simpler and more flexible way to work with random number generation by centralizing the different strategies for producing random numbers under a single interface (RandomGenerator). This allows developers to access multiple random number generation algorithms in a standardized manner. Additionally, it improves upon the legacy java.util.Random class.

Here’s how you can use the RandomGenerator API:

Key Classes/Interfaces in the RandomGenerator API

  • RandomGenerator (Interface): Defines methods for generating random values of different types (e.g., nextInt(), nextDouble(), etc.).
  • RandomGeneratorFactory (Class): Used to instantiate various implementations of the RandomGenerator interface.
  • SplittableRandom, ThreadLocalRandom, SecureRandom: Core implementations of RandomGenerator.
  • Random: Although part of the legacy API, it now implements RandomGenerator in JDK 17.

Code Example: Basic Usage with RandomGenerator

Here’s a basic example of how to use RandomGenerator:

package org.kodejava.util.random;

import java.util.random.RandomGenerator;

public class RandomGeneratorExample {
    public static void main(String[] args) {
        // Retrieve the default random generator
        RandomGenerator generator = RandomGenerator.getDefault();

        // Generate random numbers of various types
        int randomInt = generator.nextInt();          // Random integer
        double randomDouble = generator.nextDouble(); // Random double in [0.0, 1.0)
        long randomLong = generator.nextLong();       // Random long
        boolean randomBoolean = generator.nextBoolean(); // Random boolean

        // Print results
        System.out.println("Random integer: " + randomInt);
        System.out.println("Random double: " + randomDouble);
        System.out.println("Random long: " + randomLong);
        System.out.println("Random boolean: " + randomBoolean);

        // Generate a random integer within a range (0 to 100)
        int rangedInt = generator.nextInt(101);
        System.out.println("Random integer in range [0, 100]: " + rangedInt);
    }
}

Using RandomGeneratorFactory for Choosing a Specific Algorithm

The RandomGeneratorFactory class allows you to select specific implementations of RandomGenerator. This can help you use different algorithms tailored to your use case.

Example:

package org.kodejava.util.random;

import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;

public class CustomRandomGeneratorExample {
    public static void main(String[] args) {
        // List all available random generator algorithms
        System.out.println("Available Random Generators:");
        RandomGeneratorFactory.all().forEach(factory -> {
            System.out.println("- " + factory.name());
        });

        // Create a specific random generator (e.g., `L64X128MixRandom`)
        RandomGenerator generator = RandomGeneratorFactory.of("L64X128MixRandom").create();

        // Generate random values
        System.out.println("Random value: " + generator.nextDouble());
    }
}

Notes

  1. Default Generator: RandomGenerator.getDefault() provides a default random number generator.
  2. Thread-Safety: Consider java.util.concurrent.ThreadLocalRandom for generating random numbers in a multithreaded context.
  3. Secure Random Numbers: Use java.security.SecureRandom for cryptographically secure random numbers.
  4. Performance: If you need high-performance statistically random values, explore generators like L128X256MixRandom.

Benefits of Using the RandomGenerator API

  • Multiple Algorithms: No need to rely solely on java.util.Random.
  • Improved Extensibility: Selecting different implementations for specific use cases is easier.
  • Consistency: Unified method signatures across implementations enable flexible and consistent code.

How do I use Stream.generate() method?

The Stream.generate() method in Java is used to create an infinite stream of data, typically used when the programmer needs a limitless supply of data to be processed.

Here’s an example of how you might use Stream.generate():

package org.kodejava.util;

import java.util.stream.Stream;

public class StreamGenerate {
    public static void main(String[] args) {
        Stream<String> stringStream = Stream.generate(() -> "Hello, World!");

        stringStream
                .limit(5)
                .forEach(System.out::println);
    }
}

The output of this code snippet is:

Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

In this example, Stream.generate() is used to create an infinite stream of the String "Hello, World!". The limit(5) method is used to limit the infinite stream to just the first five elements, and forEach(System.out::println) is used to print each of the first five elements to the console.

However, be careful while using Stream.generate() without limit() as it can lead to infinite loop. Generally, limit() is used with Stream.generate() to avoid this.

Here’s how you would use it with the Random class to generate an infinite stream of random numbers:

package org.kodejava.util;

import java.util.Random;
import java.util.stream.Stream;

public class StreamGenerateRandomNumber {
    public static void main(String[] args) {
        Stream<Integer> randomNumbers = Stream.generate(new Random()::nextInt);

        randomNumbers
                .limit(10)
                .forEach(System.out::println);
    }
}

This will output something like:

-2134800739
730041861
357210260
1964364949
-1083197494
-1988345642
-1851656161
-562751737
-1777126198
-1030758565

In this case, new Random()::nextInt is a supplier function that provides an infinite stream of random integers. The limit(10) method is used to limit the stream to the first 10 random integers.

How do I generate random alphanumeric strings?

The following code snippet demonstrates how to use RandomStringGenerator class from the Apache Commons Text library to generate random strings. To create an instance of the generator we can use the RandomStringGenerator.Builder() class build() method. The builder class also helps us to configure the properties of the generator. Before calling the build() method we can set the properties of the builder using the following methods:

  • withinRange() to specifies the minimum and maximum code points allowed in the generated string.
  • filteredBy() to limits the characters in the generated string to those that match at least one of the predicates supplied. Some enum for the predicates: CharacterPredicates.DIGITS, CharacterPredicates.LETTERS.
  • selectFrom() to limits the characters in the generated string to those who match at supplied list of Character.
  • usingRandom() to overrides the default source of randomness.

After configuring and building the generator based the properties defined, we can generate the random strings using the generate() methods of the RandomStringGenerator. There are two methods available:

  • generate(int length) generates a random string, containing the specified number of code points.
  • generate(int minLengthInclusive, int maxLengthInclusive) generates a random string, containing between the minimum (inclusive) and the maximum (inclusive) number of code points.

And here is your code snippet:

package org.kodejava.commons.text;

import org.apache.commons.text.CharacterPredicates;
import org.apache.commons.text.RandomStringGenerator;

public class RandomStringDemo {
    public static void main(String[] args) {
        RandomStringGenerator generator = new RandomStringGenerator.Builder()
                .withinRange('0', 'z')
                .filteredBy(CharacterPredicates.DIGITS, CharacterPredicates.LETTERS)
                .build();

        for (int i = 0; i < 10; i++) {
            System.out.println(generator.generate(10, 20));
        }
    }
}

Below are examples of generated random alphanumeric strings:

weJDtVARLIFS96WXje
FYrNzTR3Q3dUrLT3Xsc
4F1fu8nSsA
nIQi3a4Oyv9
l6QcsP9bejdbaLd2jd
Cc9YgTfgwo
2B8un8YCcxn9m2
RAN2dZAWalUIWeZeoS
jPQspicyaKfAzS14twH
GTurc0lWkSid03rG0JZ

Apache Logo

Maven Dependencies

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.12.0</version>
</dependency>

Maven Central

How do I generate random string?

package org.kodejava.security;

import java.security.SecureRandom;
import java.util.Random;

public class RandomString {
    public static final String SOURCES =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";

    public static void main(String[] args) {
        RandomString rs = new RandomString();
        System.out.println(rs.generateString(new Random(), SOURCES, 10));
        System.out.println(rs.generateString(new Random(), SOURCES, 10));
        System.out.println(rs.generateString(new SecureRandom(), SOURCES, 15));
        System.out.println(rs.generateString(new SecureRandom(), SOURCES, 15));
    }

    /**
     * Generate a random string.
     *
     * @param random     the random number generator.
     * @param characters the characters for generating string.
     * @param length     the length of the generated string.
     */
    public String generateString(Random random, String characters, int length) {
        char[] text = new char[length];
        for (int i = 0; i < length; i++) {
            text[i] = characters.charAt(random.nextInt(characters.length()));
        }
        return new String(text);
    }
}

Example string produced by the code snippets are:

bJGjSgoy7G
SoeTjBy83s
IolJZtkttJixAVY
ZOvQnICNcwcCdJ8

How to get random key-value pair from Hashtable?

package org.kodejava.example.util;

import java.util.Hashtable;
import java.util.Random;

public class HashtableGetRandom {
    public static void main(String[] args) {
        // Create a hashtable and put some key-value pair.
        Hashtable<String, String> colors = new Hashtable<>();
        colors.put("black", "#000");
        colors.put("red", "#f00");
        colors.put("green", "#0f0");
        colors.put("blue", "#00f");
        colors.put("white", "#fff");

        // Get a random entry from the hashtable.
        String[] keys = colors.keySet().toArray(new String[colors.size()]);
        String key = keys[new Random().nextInt(keys.length)];
        System.out.println(key + " = " + colors.get(key));
    }
}