range
integers
random
Java

How do I generate random integers within a specific range in Java?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Generating a random integer in Java is straightforward once you are clear about whether the upper bound is inclusive or exclusive. The best API also depends on context: ThreadLocalRandom is a strong default for most application code, while SecureRandom is the right choice for security-sensitive values.

The Most Common Need: Inclusive Range

Suppose you want a random integer from min through max, inclusive. With ThreadLocalRandom, the usual pattern is:

java
1import java.util.concurrent.ThreadLocalRandom;
2
3public class Main {
4    public static void main(String[] args) {
5        int min = 10;
6        int max = 20;
7
8        int value = ThreadLocalRandom.current().nextInt(min, max + 1);
9        System.out.println(value);
10    }
11}

This works because nextInt(origin, bound) uses an inclusive lower bound and an exclusive upper bound. Adding 1 turns max into an inclusive endpoint.

Using Random

Random is also fine for many ordinary use cases.

java
1import java.util.Random;
2
3public class Main {
4    public static void main(String[] args) {
5        Random random = new Random();
6
7        int min = 10;
8        int max = 20;
9        int value = random.nextInt((max - min) + 1) + min;
10
11        System.out.println(value);
12    }
13}

The logic is:

  • '(max - min) + 1 gives the number of possible values'
  • 'nextInt(...) picks an offset from 0 up to that count minus one'
  • adding min shifts the result into the target range

Why ThreadLocalRandom Is Often Better

ThreadLocalRandom is especially good in concurrent code because it avoids shared Random contention.

A practical rule is:

  • use ThreadLocalRandom in ordinary multi-threaded application code
  • use Random when you want a simple explicitly owned generator instance

For modern server-side Java, ThreadLocalRandom is often the cleaner default.

Security-Sensitive Random Numbers Need SecureRandom

If the number is used for tokens, passwords, security codes, or anything adversarial, do not use Random or ThreadLocalRandom. Use SecureRandom.

java
1import java.security.SecureRandom;
2
3public class Main {
4    public static void main(String[] args) {
5        SecureRandom random = new SecureRandom();
6
7        int min = 100000;
8        int max = 999999;
9        int value = random.nextInt((max - min) + 1) + min;
10
11        System.out.println(value);
12    }
13}

This is slower than ordinary pseudo-random generation, but it is the right tool when unpredictability matters.

Inclusive And Exclusive Bounds Cause Most Bugs

Many mistakes come from forgetting that Java range APIs often use exclusive upper bounds.

For example:

java
int value = ThreadLocalRandom.current().nextInt(10, 20);

This returns values from 10 through 19, not 20.

If you need the upper endpoint included, adjust accordingly.

A Reusable Helper Method

A helper method makes the contract explicit.

java
1import java.util.concurrent.ThreadLocalRandom;
2
3public class Main {
4    public static int randomInclusive(int min, int max) {
5        if (min > max) {
6            throw new IllegalArgumentException("min must be <= max");
7        }
8        return ThreadLocalRandom.current().nextInt(min, max + 1);
9    }
10
11    public static void main(String[] args) {
12        System.out.println(randomInclusive(1, 6));
13    }
14}

This is useful for dice rolls, test data, and bounded random selection.

What About Math.random()?

You can also do this with Math.random():

java
int value = (int) (Math.random() * ((max - min) + 1)) + min;

It works, but it is usually less explicit and less flexible than the dedicated random classes. In modern Java code, ThreadLocalRandom, Random, or SecureRandom are better choices.

Common Pitfalls

The most common mistake is forgetting whether the upper bound is inclusive or exclusive.

Another mistake is using Random for security-sensitive values. It is not designed for that.

Developers also sometimes forget to validate the range and end up with negative widths or min > max bugs.

Finally, using Math.random() everywhere can make intent less clear than using the dedicated random APIs.

Summary

  • For an inclusive range, use ThreadLocalRandom.current().nextInt(min, max + 1).
  • 'Random is also valid for ordinary non-concurrent use.'
  • Use SecureRandom for security-sensitive values.
  • Be explicit about inclusive versus exclusive bounds.
  • Wrap the logic in a helper method if the range generation appears often in your code.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.