Java mainly provides four random number generator API's depending of your use case.
java.lang.Math.random()
If we check the Math class source code, we can view this:
private static Random randomNumberGenerator;
private static synchronized void initRNG() {
if (randomNumberGenerator == null)
randomNumberGenerator = new Random();
}
public static double random() {
if (randomNumberGenerator == null) initRNG();
return randomNumberGenerator.nextDouble();
}
Math.random() is simply a shortcut to call Random Class. It is more simple and less complete than java.util.Random but it's enough in some cases.
java.util.Random
The Random class implement a Linear Congruential Generator.
LCG is a pretty simple formula for Pseudorandom Number Generation. java.util.Random is not trully random, it is totally deterministric. With the same initial condition (also called the seed), you've got the same result in the same order.
Use java.util.Random is good for the most use cases (simulation, games, ...) but is not good for cryptography because of his predictability, for this kind of use case prefer java.security.SecureRandom.
java.util.Random is thread safe but can have performance issues in multi-threaded context. If you work in a multi-threaded application, prefer ThreadLocalRandom.
java.security.SecureRandom
The SecureRandom class extend java.util.Random class to implement a cryptographically strong random number generator based on an entropy source. SecureRandom is not deterministic.
SecureRandom have multiple implementation in function of your platform (the complete implementation list).
java.security.SecureRandom is less fast than java.util.Random because of entropy source.
java.util.concurrent.ThreadLocalRandom
The ThreadLocalRandom class is another implementation of Linear Congruential Generator but this one isn't thread-safe but dedicated to a specific thread.
This implementation is more fast than java.util.Random in multi-threaded context.
In your case, you could use java.util.Collections.shuffle(list) to shuffle your array with java.util.Random or with a specific Random Generator like java.security.SecureRandom.
Videos
Java mainly provides four random number generator API's depending of your use case.
java.lang.Math.random()
If we check the Math class source code, we can view this:
private static Random randomNumberGenerator;
private static synchronized void initRNG() {
if (randomNumberGenerator == null)
randomNumberGenerator = new Random();
}
public static double random() {
if (randomNumberGenerator == null) initRNG();
return randomNumberGenerator.nextDouble();
}
Math.random() is simply a shortcut to call Random Class. It is more simple and less complete than java.util.Random but it's enough in some cases.
java.util.Random
The Random class implement a Linear Congruential Generator.
LCG is a pretty simple formula for Pseudorandom Number Generation. java.util.Random is not trully random, it is totally deterministric. With the same initial condition (also called the seed), you've got the same result in the same order.
Use java.util.Random is good for the most use cases (simulation, games, ...) but is not good for cryptography because of his predictability, for this kind of use case prefer java.security.SecureRandom.
java.util.Random is thread safe but can have performance issues in multi-threaded context. If you work in a multi-threaded application, prefer ThreadLocalRandom.
java.security.SecureRandom
The SecureRandom class extend java.util.Random class to implement a cryptographically strong random number generator based on an entropy source. SecureRandom is not deterministic.
SecureRandom have multiple implementation in function of your platform (the complete implementation list).
java.security.SecureRandom is less fast than java.util.Random because of entropy source.
java.util.concurrent.ThreadLocalRandom
The ThreadLocalRandom class is another implementation of Linear Congruential Generator but this one isn't thread-safe but dedicated to a specific thread.
This implementation is more fast than java.util.Random in multi-threaded context.
In your case, you could use java.util.Collections.shuffle(list) to shuffle your array with java.util.Random or with a specific Random Generator like java.security.SecureRandom.
Use java.util.Random API
An instance of this class is used to generate a stream of pseudorandom numbers. The class uses a 48-bit seed, which is modified using a linear congruential formula. (See Donald Knuth, The Art of Computer Programming, Volume 3, Section 3.2.1.)
Algorithm class : pseudorandom number generator known as PRNG. You can read more about it here.
Note : Math.random() also uses java.util.Random instance to generate the psuedo-random numbers internally
I've looked up the source code and this was the purpose statement:
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range. When this method is first called, it creates a single new pseudorandom-number generator, exactly as if by the expression new java.util.Random() This new pseudorandom-number generator is used thereafter for all calls to this method and is used nowhere else. This method is properly synchronized to allow correct use by more than one thread. However, if many threads need to generate pseudorandom numbers at a great rate, it may reduce contention for each thread to have its own pseudorandom-number generator.
What does this mean? How does it return a different double each time? I've always been incredibly curious as to how random number generators worked.
They want to alert you to the fact that Math.random is not a true random generator but a PRNG. If you need this to be safe you need a CSPRNG.
Here is the spec
Using PseudoRandom Number Generators (PRNGs) is security-sensitive
When software generates predictable values in a context requiring unpredictability, it may be possible for an attacker to guess the next value that will be generated, and use this guess to impersonate another user or access sensitive information.
As the Math.random() function relies on a weak pseudorandom number generator, this function should not be used for security-critical applications or for protecting sensitive data. In such context, a Cryptographically Strong PseudoRandom Number Generator (CSPRNG) should be used instead.
Ask Yourself Whether
- the code using the generated value requires it to be unpredictable. It is the case for all encryption mechanisms or when a secret value, such as a password, is hashed.
- the function you use generates a value which can be predicted (pseudo-random).
- the generated value is used multiple times.
- an attacker can access the generated value.
You are at risk if you answered yes to the first question and any of the following ones.
Code example
const crypto = window.crypto || window.msCrypto;
var array = new Uint32Array(1);
crypto.getRandomValues(array); // Compliant for security-sensitive use cases
const FileId = array[0];
console.log(FileId);
As the
java.util.Randomclass relies on a pseudorandom number generator, this class and relatingjava.lang.Math.random()method should not be used for security-critical applications or for protecting sensitive data. In such context, thejava.security.SecureRandomclass which relies on a cryptographically strong random number generator (RNG) should be used in place.
SecureRandom random = new SecureRandom(); // Compliant for security-sensitive use cases
int bound = 100;
random.nextInt(bound);
Ref: https://rules.sonarsource.com/java/RSPEC-2245