Explain Codes LogoExplain Codes Logo

Java: random long number in 0 <= x < n range

java
random-number-generation
threadlocalrandom
splittablerandom
Anton ShumikhinbyAnton Shumikhin·Nov 2, 2024
TLDR

Generate a random long number, in the [0, n) range, using Java's ThreadLocalRandom.current().nextLong(n):

long randomLong = ThreadLocalRandom.current().nextLong(n); // The number you're looking for, with 0 <= randomLong < n

Voila! This generates a random long that strictly stays within 0 (included) and n (excluded).

Selecting the right toolkit

For multi-threaded environments: ThreadLocalRandom

In a thread-happy application, ThreadLocalRandom is a blessing in disguise due to superior performance in such environments. It also lets you set origin and bound with precision:

long randomLongInRange = ThreadLocalRandom.current().nextLong(origin, bound); // Origin says hi, bound waves bye...

The above generates a random long value that shakes hands with origin (included) and bids adieu to bound (excluded).

For reproduceable sequences: SplittableRandom

When tests call for identical sequences of randomness, guess who splits the mic? SplittableRandom:

SplittableRandom splittableRandom = new SplittableRandom(seed); long splitRandom = splittableRandom.nextLong(origin, bound); // Feeding the same seed every time gets you the same "random" sequence. Magic, right?

By tossing in a seed, you can replant the same random sequence anytime, a nifty trait when you need consistent test results.

Diving into alternatives and steering clear of pitfalls

The old school way: Math.random()

When no fancy libraries or utility classes accompany you, Math.random() stands by your side, combined with a touch of explicit casting:

long randomNumber = (long)(Math.random() * n); // Dusting off the classics...

A red flag: modulo bias

It's tempting to play with the modulo operator to cage a random long, but beware! It may open the door to bias:

long biasedRandomNumber = (randomLong() % n); // Don't let the modulo munchkin mislead you!

This leads to an uneven distribution of numbers across the range, creating a bias. Refrain from this to ensure fair randomness across the spectrum.

Handling the extreme cases

When building a custom bounded method or using any random generation technique, pause and ponder — are all edge cases handled? Consider when n is zero, negative, or busts the normal numeric limits.

Fancy features with Apache Commons Lang

Craving more candy on your plate? Meet Apache Commons Lang's RandomUtils:

long randomLong = RandomUtils.nextLong(lower, upper); // Because sometimes, vanilla Java could use a little bit of topping!

A cup of Apache commons offers lower and upper bound flavored randomness through RandomUtils.nextLong() method.

Tackling the trade-offs

Count the cost for your specific use-case. Although ThreadLocalRandom charms concurrent scenarios, SplittableRandom might amp up the performance for single-thread contexts. Weigh the capabilities against the requirements to pick the most apt approach for your random generation needs.