Saturday, 18 June 2022

Quick guide to generate random data in Java

Random data is the collection of data with no determined order.

 


What is pseudo random data?

Pseudo random data is a statistically random data produced by a computer algorithm. Since the data is produced by an algorithm, pseudo random data is not actual random data.

 

There are 4 primary approaches to product random data in Java.

a.   Using Math.random() method

b.   Using Random class

c.    Using ThreadLocalRandom class

d.   Using SecureRandom class

 

 

Approach 1: Using Math.random() method

Math.random() method return a double positive value that greater than or equal to 0.0 and less than 1.0.

 

Signature

public static double random()

 

Example 1: Get a random integer between two values, the returned value is >= min and less than max.

private static int getRandomNumberMinInclusiveMaxExclusive(int min, int max) {
	return (int) (Math.random() * (max - min) + min);
}

Example 2: Get aRandom number that is inclusive at both the minimum and the maximum.

 

private static int getRandomIntMaxAndMinInclusive(int min, int max) {
	return (int) Math.floor(Math.random() * (max - min + 1) + min);
}

 

Find the below working application.

 

MathRandomDemo.java

 

package com.sample.app;

public class MathRandomDemo {

	// Get random integer between two values, the returned value is >= min and less
	// than max
	private static int getRandomNumberMinInclusiveMaxExclusive(int min, int max) {
		return (int) (Math.random() * (max - min) + min);
	}

	// Random number is inclusive at both the minimum and the maximum
	private static int getRandomIntMaxAndMinInclusive(int min, int max) {
		return (int) Math.floor(Math.random() * (max - min + 1) + min);
	}

	public static void main(String[] args) {
		for (int i = 0; i < 10; i++)
			System.out.println("random number between 10 and 20 is : " + getRandomNumberMinInclusiveMaxExclusive(10, 20));

		System.out.println("----------------------");

		for (int i = 0; i < 10; i++)
			System.out.println("random number between 10 and 20 is : " + getRandomIntMaxAndMinInclusive(10, 20));
	}

}

 

Sample Output

random number between 10 and 20 is : 16
random number between 10 and 20 is : 12
random number between 10 and 20 is : 14
random number between 10 and 20 is : 12
random number between 10 and 20 is : 12
random number between 10 and 20 is : 13
random number between 10 and 20 is : 15
random number between 10 and 20 is : 19
random number between 10 and 20 is : 12
random number between 10 and 20 is : 10
----------------------
random number between 10 and 20 is : 18
random number between 10 and 20 is : 13
random number between 10 and 20 is : 17
random number between 10 and 20 is : 16
random number between 10 and 20 is : 18
random number between 10 and 20 is : 17
random number between 10 and 20 is : 16
random number between 10 and 20 is : 16
random number between 10 and 20 is : 10
random number between 10 and 20 is : 18

 

Approach 2: Using Random class

One drawback of Math.random() class is, it return a double value, what if you want to get a random byte array, long, Boolean etc., Here we can use java.util.Random class.

 

Below table summarizes the methods provided by Random class to generate random data.

 

Method

Description

public boolean nextBoolean()

Returns the next pseudorandom, uniformly distributed boolean value from this random number generator's sequence.

public void nextBytes(byte[] bytes)

Generates random bytes and places them into a user-supplied byte array.  The number of random bytes produced is equal to the length of the byte array.

public double nextDouble()

Returns the next pseudorandom, uniformly distributed double value between 0.0 and 1.0 from this random number generator's sequence.

public float nextFloat()

Returns the next pseudorandom, uniformly distributed float value between 0.0 and 1.0 from this random number generator's sequence.

synchronized public double nextGaussian()

Returns the next pseudorandom, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.

public int nextInt()

Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence.

public int nextInt(int bound)

Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.

public long nextLong()

Returns the next pseudorandom, uniformly distributed long value from this random number generator's sequence.

 

Find the below working application.

 

RandomClassDemo.java

package com.sample.app;

import java.util.Random;

public class RandomClassDemo {

	public static void main(String[] args) {
		Random random = new Random();

		boolean boolValue = random.nextBoolean();

		byte[] arr = new byte[10];
		random.nextBytes(arr);

		double doubleValue = random.nextDouble();
		float floatValue = random.nextFloat();
		double gaussianValue = random.nextGaussian();
		int intValue = random.nextInt();
		int intBoundVal = random.nextInt(10);
		long longValue = random.nextLong();

		System.out.println("boolValue : " + boolValue);

		System.out.println("Data in byte array:");
		for (byte b : arr) {
			System.out.print(b + " ");
		}

		System.out.println("\ndoubleValue : " + doubleValue);
		System.out.println("floatValue : " + floatValue);
		System.out.println("gaussianValue : " + gaussianValue);
		System.out.println("intValue : " + intValue);
		System.out.println("intBoundVal : " + intBoundVal);
		System.out.println("longValue : " + longValue);

	}

}

 

Output

boolValue : false
Data in byte array:
-103 83 -68 -99 86 9 -58 37 -121 -58 
doubleValue : 0.20895136759695598
floatValue : 0.4006803
gaussianValue : 1.9802811894382149
intValue : 2089366724
intBoundVal : 4
longValue : 1076180557500076931

 

Additionally, you can provide a seed while initializing Random object. A random seed is a number used to initialize a pseudorandom number generator.

 

Example

Random random = new Random(18674109);

 

Above snippet use 18674109 as seed value.

 

There are couple of problems with Random class.

a. it internally use an AtomicLong value (as seed) for random number generation. Even though it is thread safe, if multiple threads are working on same Random object, it may lead to some performance implications.

b. It do not provide actual random ness, but only pseudo-randomness. We can address this problem using SecureRandom class, I will explain about this later in this post.

c. If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.

 

Approach 3: Using ThreadLocalRandom. Similar to Random class, ThreadLocalRandom class provide nextX methods to generate random data. ThreadLocalRandom is a subclass of Random class.

 

Since ThreadLocalRandom number generator isolated to the current thread, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention. Use of ThreadLocalRandom is particularly appropriate when multiple tasks (for example, each a ForkJoinTask use random numbers in parallel in thread pools.

 

Below table summarizes the methods provided by ThreadLocalRandom to generate random data.

 

Method

Description

public boolean nextBoolean()

Returns a pseudorandom boolean value.

public void nextBytes(byte[] bytes)

Generates random bytes and places them into a user-supplied byte array.

public double nextDouble()

Returns a pseudorandom double value between zero (inclusive) and one (exclusive).

public double nextDouble(double bound)

Returns a pseudorandom double value between 0.0 (inclusive) and the specified bound (exclusive). This method throws IllegalArgumentException if bound is not positive.

public double nextDouble(double origin, double bound)

Returns a pseudorandom double value between the specified origin (inclusive) and bound (exclusive). This method throws an IllegalArgumentException if origin is greater than or equal to bound.

public float nextFloat()

Returns a pseudorandom float value between zero (inclusive) and one (exclusive).

public double nextGaussian()

Returns the next pseudorandom, Gaussian ("normally") distributed double value with mean 0.0 and standard deviation 1.0 from this random number generator's sequence.

public int nextInt()

Returns a pseudorandom int value.

public int nextInt(int bound)

Returns a pseudorandom int value between zero (inclusive) and the specified bound (exclusive). This method throws an IllegalArgumentException if bound is not positive.

public int nextInt(int origin, int bound)

Returns a pseudorandom int value between the specified origin (inclusive) and the specified bound (exclusive). This method throws an IllegalArgumentException if origin is greater than or equal to bound.

public long nextLong()

Returns a pseudorandom long value.

public long nextLong(long bound)

Returns a pseudorandom long value between zero (inclusive) and the specified bound (exclusive). This method throws IllegalArgumentException if bound is not positive.

public long nextLong(long origin, long bound

Returns a pseudorandom long value between the specified origin (inclusive) and the specified bound (exclusive). throws IllegalArgumentException if origin is greater than or equal to bound.

 

Find the below working application.

 

ThreadLocalRandomDemo.java

package com.sample.app;

import java.util.concurrent.ThreadLocalRandom;

public class ThreadLocalRandomDemo {
	public static void main(String[] args) {
		ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();

		boolean boolVal = threadLocalRandom.nextBoolean();

		byte[] bytesData = new byte[10];
		threadLocalRandom.nextBytes(bytesData);

		double doubleVal1 = threadLocalRandom.nextDouble();
		double doubleVal2 = threadLocalRandom.nextDouble(10);
		double doubleVal3 = threadLocalRandom.nextDouble(0, 10);

		float floatVal = threadLocalRandom.nextFloat();

		double gaussianVal = threadLocalRandom.nextGaussian();

		int intVal1 = threadLocalRandom.nextInt();
		int intVal2 = threadLocalRandom.nextInt(10);
		int intVal3 = threadLocalRandom.nextInt(0, 10);

		long longVal1 = threadLocalRandom.nextLong();
		long longVal2 = threadLocalRandom.nextLong(10);
		long longVal3 = threadLocalRandom.nextLong(0, 10);

		System.out.println("boolVal : " + boolVal);

		for (byte b : bytesData) {
			System.out.print(b + " ");
		}
		System.out.println();

		System.out.println("doubleVal1 : " + doubleVal1);
		System.out.println("doubleVal2 : " + doubleVal2);
		System.out.println("doubleVal3 : " + doubleVal3);
		System.out.println("floatVal : " + floatVal);
		System.out.println("gaussianVal : " + gaussianVal);
		System.out.println("intVal1 : " + intVal1);
		System.out.println("intVal2 : " + intVal2);
		System.out.println("intVal3 : " + intVal3);
		System.out.println("longVal1 : " + longVal1);
		System.out.println("longVal2 : " + longVal2);
		System.out.println("longVal3 : " + longVal3);

	}

}

 

Sample Output

boolVal : false
118 -19 -34 108 62 -97 71 -86 59 126 
doubleVal1 : 0.34651766819920815
doubleVal2 : 8.44772447992309
doubleVal3 : 6.626061934684642
floatVal : 0.9201188
gaussianVal : -0.5276663370928654
intVal1 : 1957939933
intVal2 : 1
intVal3 : 9
longVal1 : 3661422727668556698
longVal2 : 8
longVal3 : 2

 

Note that Instances of ThreadLocalRandom are not cryptographically secure. Better to use java.security.SecureRandom in security-sensitive applications.

 

Approach 4: Using SecureRandom class.

SecureRandom class provides provides a cryptographically strong random number generator. All SecureRandom output sequences must be cryptographically strong, as described in RFC 1750: Randomness Recommendations for Security.

 

You can get an instance of SecureRandom algorithm by calling getInstance() or getInstanceStrong() methods.

 

public static SecureRandom getInstance(String algorithm)

public static SecureRandom getInstance(String algorithm, String provider)

public static SecureRandom getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException

Returns a SecureRandom object that implements the specified Random Number Generator (RNG) algorithm. 'algorithm' the name of the RNG algorithm. At the time of writing this post, below algorithms supported.

a.   NativePRNG

b.   NativePRNGBlocking

c.    NativePRNGNonBlocking

d.   PKCS11

e.   SHA1PRNG

f.     Windows-PRNG

 

You can get more details about these algorithms from below link.

https://docs.oracle.com/en/java/javase/18/docs/specs/security/standard-names.html#securerandom-number-generation-algorithms

 

public static SecureRandom getInstanceStrong() throws NoSuchAlgorithmException

SecureRandom object that was selected by using the algorithms/providers specified in the securerandom.strongAlgorithms Security property.

 

Below snippet print the secure random algorithms.

 

SecureRandomAlgorithms.java

package com.sample.app;

import java.security.Security;

public class SecureRandomAlgorithms {
	
	public static void main(String[] args) {
		String secureRandomAlgos = Security.getProperty("securerandom.strongAlgorithms");
		System.out.println(secureRandomAlgos);
	}

}

Since SecureRandom class extends Random class, all the methods provided by Random class are available to SecureRandom object.

 

 

 

 

 

References

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/security/SecureRandom.html

https://tersesystems.com/blog/2015/12/17/the-right-way-to-use-securerandom/

http://www.ietf.org/rfc/rfc1750.txt

https://docs.oracle.com/en/java/javase/18/docs/specs/security/standard-names.html#securerandom-number-generation-algorithms

https://openjdk.java.net/jeps/123

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Random.html

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/security/Security.html

https://tersesystems.com/blog/2015/12/17/the-right-way-to-use-securerandom/

 

You may like

 

Interview Questions

How to solve the Error: Could not find or load main?

float vs double in Java

Quick guide to race condition in Java with examples

How to read the file content using an iterator in Java?

Implement a Closeable iterator in Java

 

 

 

No comments:

Post a Comment