Saturday, July 31, 2021

3 ways to create random numbers in a range in Java - Examples

Many times you need to generate random numbers, particular integers in a range but unfortunately, JDK doesn't provide a simple method like nextIntegerBetween(int minInclusive, int maxExclusive), because of that many Java programmers, particularly beginners struggle to generate random numbers between a range, like random integers between 1 to 6 if you are creating a game of dice, or a random number between 1 to 52 if you are creating a game of playing cards, and you need to choose a random card, or most commonly random numbers between 1 to 10 and 1 to 100. Then, the question comes, how to solve this problem? How to generate random int values between a range? Well, you need to do a little bit of work.

Even though JDK doesn't provide a simple solution, it provides all the tools you need to generate those random numbers.  The support of random numbers exists from JDK 1 via Math.random() method which returns a random number, albeit a floating-point value, a double between 0 and 1.

If you are good at maths, you can use that method to generate a random number between any range, but that's not the best approach, particularly if you need integer values and not the float or double.

The next and suggested approach is to use the java.util.Random class generates random numbers and provides methods to make an arbitrary integer, long, float, double, and even boolean values. You can use the nextInt() method to generate random integers. Though, you also need to apply a little bit of Mathematics to generate random integers between two numbers.

The third and probably the best approach to generate random integers in a range is to use a general-purpose Java library like Apache Commons Lang, which provides a class called RandomUtils. This has a method public static int nextInt(int startInclusive, int endExclusive), which returns a random integer within the specified range.

In this article, I'll go through each of these approaches apart from the Math.random(), and we'll see code examples to create random numbers in a range, like 1 to 10 or 1- 52 or 1- 6, etc. Btw, if you are starting with Java and a beginner in this field, I suggest you join a comprehensive course like The Complete Java Masterclass on Udemy. This is also the most up-to-date course to learn Java and recently updated to cover the latest JDK version.




Generating Random integers between 1 to 6 using java.util.Random

The first and common way to generate random numbers, like integers or long is by using the java.util.Random class. This method provides methods like nextInt() or nextLong() to get the random int or long value.

If you need random integer in a range then we need to use the overloaded nextInt(int bound) method which returns a random integer between 0 (inclusive) and bound (exclusive), binding is nothing but the maximum value in your range.

In order to generate a random value between a range,  like 1 to 6, we can apply a little bit of maths, as shown below:

/**
*
* @param start - the first number in the range
* @param end - last or maximum number in the range
* @return - a random number in the range
*/
public static int getRandomInRange(int start, int end){
   return start + generator.nextInt(end - start + 1);
}

So, for example, if you need a random integer between 5 and 10 you can do something like:
int random = 5 + Random.nextInt(10 - 5 + 1);
or
int random = 5 + Random.nextInt(6)

Since nextInt() will return an integer between 0 and 6 (exclusive) the maximum value returned by this would be between 0 and 5 and by adding 5 you get the random value between 5 and 10.

The generator in the above utility method is an instance of java.util.Random class, which is encapsulated in a class-level variable because it's not advisable to generate an instance of java.util.Random every time you need a random number.

You can reuse the same instance for better performance. Btw, If you need random numbers for a real-world project, I would suggest using a  library, instead of re-inventing the wheel, as suggested in Effective Java 3rd Edition by Joshua Bloch.




Random Integers in a range using ThreadLocalRandom of JDK7

If you are running in JDK 7 or JDK 8 or maybe on JDK 9, then you can use the class ThreadLocalRandom from Java 7 to generate random numbers in Java. This class is equivalent to java.uti.Random in a concurrent environment.

 It's more efficient because random numbers are generated locally on each thread and it's the preferred approach on a multi-threaded application. You can assume that each Thread kept its own random number generator inside a ThreadLocal variable.

This class provides a method like what I have described in the opening phrase, e.g. nextInt(origin, bound), which returns a pseudorandom int value between the specified origin (inclusive) and the specified bound (exclusive). This is probably the easiest way to generate random int values between a range in Java without using an external, third-party library.

Here is the code example of using ThreadLocalRandom to generate random integers between 1 to 10 in Java:
int randomBetweenOneTo100 = ThreadLocalRandom
                              .current()
                              .nextInt(1, 10 + 1);

Since the bound is exclusive, you need to increase the range by + 1. For example to generate int values between 1 to 10, you need to call nextInt(1, 10 + 1) or nextInt(1, 11).

Similarly, if you need random integers between 5 and 10, then you need to call nextInt(5, 11) because 5 is inclusive, but 11 is exclusive, this will return any value between 5 and 10.

Btw, if you want to learn more about ThreadLocalRandom and ThreadLocal variable in Java, I suggest you go through Coursera's  Java Programming and Software Engineering Fundamentals Specialization which covers this and other essential concepts of Java. All the courses in the specialization are free-to-audit but you need to pay if you need a certification.

How to Generate Random Integers on a Range in Java


Random Int values in a specified range using RandomUtils of Apache Commons

The third and probably the best way to generate random int values in a given interval is by using the nextInt(int startInclusive, int endExclusive) of RandomUtils class from Apache Commons Lang 3.4.

This method is similar to the nextInt(int origin, int bound) of JDK 7 ThreadLocalRandom but the good thing is that you can use it on your application even if you are not running on Java 7, e.g. still running on Java SE 6.

I generally follow advice from Effective Java, particularly the one about using tried and tested library instead of creating your own stuff for everyday things, and that's why I always include this library in my project.

3 Ways to Generate Random Numbers on a Range in Java

Here is an example of using this method to generate random integers in a range, e.g. between 1 and 52 to randomly choose a card in a pack of playing cards:

int random = RandomUtils.nextInt(1, 52 + 1);

As the name suggests it returns int values for a given range but only start is inclusive. Since the bound is exclusive, you probably need to increase the range by 1 to get the values precisely between the range.



Java Program to generate random numbers between a range

Now that, you understand the different ways to make random numbers in Java, particularly in a specified range, let's see a complete Java program that uses these methods to actually generate random values and display it on a console.

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.commons.lang3.RandomUtils;

public class HelloWorld {

  private static final Random generator = new Random();

  public static void main(String[] args) {

    // code to generate random number between 1 to 10
    // using ThreadLocal

    System.out.println("generating random number in range"
        + " ( 1- 10) using ThreadLocalRandom");

    for (int i = 0; i < 10; i++) {
      int randomBetweenOneTo100 = ThreadLocalRandom
                                    .current()
                                    .nextInt(1,10 + 1);
      System.out.print(randomBetweenOneTo100 + " ");
    }
    System.out.println();

    // using java.util.Random
    System.out.println("generating random number in range"
            + " (1 -52) using java.util.Random");

    for (int i = 0; i < 10; i++) {
      int random = getRandomInRange(1, 52);
      System.out.print(random + " ");
    }
    System.out.println();

    
    // 3rd and best approach - use Apache Commons RandomUtils
    System.out.println("generating random number in range "
        + "(1 -6) using Apache Commons RandomUtils");

    for (int i = 0; i < 10; i++) {
      int random = RandomUtils.nextInt(1, 7);
      System.out.print(random + " ");
    }
    System.out.println();

  }

  /**
   * @param start - the first number in range
   * @param end - last or maximum number in range
   * @return - a random number within given range
   */

  public static int getRandomInRange(int start, int end) {
    return start + generator.nextInt(end - start + 1);

  }

}

Output:
Generating a random number in the range ( 1- 10) using ThreadLocalRandom
9 2 3 1 10 5 7 7 10 4
Generating a random number in the range (1 -52) using java.util.Random
48 9 13 50 28 34 44 19 51 29
Generating a random number in the range (1 -6) using Apache Commons RandomUtils
6 6 4 2 3 3 1 5 5 1

You can see that in all examples, we have successfully generated int values that are in the specified range, i.e. 1 to 10, 1 to 52, and 1 to 6. You can do the same to generate int values in the field you want.

3 Ways to Generate Random Integers in Java


Important points to Remember

Now that you know how to generate random numbers in Java, particularly random integers in between a range, let's revise some of the critical points:

1) The Math.random() returns a double value between 0 and 1, which can be used to generate random integers but is not suitable.

2) The preferred way to generate random integer values is by using the nextInt(bound) method of java.util.Random class. This method returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive). You can then tweak it to ensure costs are in the specified range.


3) The JDK 7 introduced a new class called ThreadLocalRandom, which is equivalent to class java.util.Random for the multithreaded environment. In this case, a random number is generated locally in each of the threads.

So we have a better performance by reducing the contention. If you want to know more about ThreadLocalRandom, I suggest you read The Definitive Guide to Java Performance by Scott Oaks, he has an excellent write-up on that topic.

3 Ways to Generate Random Integers on a Range in Java

4) The best way to generate random integers between a range is by using the RandomUtils class from Apache Commons Lang. This was added to a newer version of Apache commons-lang and returns an integer value between two given numbers.

5) In order to use RandomUtils class, you need to include the commons-lang3-3.4.jar in your project's classpath, or you need to import this dependency using Maven.

That's all about how to generate random numbers between a range. We have seen 3 ways to create random integer values between giving a range, e.g. between minimum and maximum. You can adjust the code to make sure that peak is exclusive or inclusive.

You can use any of three methods, but I suggest you follow Joshua Bloch's advice of Effective Java, now updated for JDK 8 and 9, about using a library instead of creating your own methods and that's why the RandomUtils from Apache commons looks the best away along with ThreadLocalRandom from JDK 7.


Related Java  Tutorials
If you are interested in learning more about Java and Java 8, here are my earlier articles covering some of the essential concepts of Java 8
  • 5 Books to Learn Java 8 from Scratch (books)
  • 10 Things Java Programmer should learn (things)
  • How to use Stream class in Java 8 (tutorial)
  • How to use filter() method in Java 8 (tutorial)
  • How to sort the map by keys in Java 8? (example)
  • What is the default method in Java 8? (example)
  • How to format/parse the date with LocalDateTime in Java 8? (tutorial)
  • How to use peek() method in Java 8 (example)
  • How to sort the may by values in Java 8? (example)
  • How to join String in Java 8 (example)
  • 5 Free Courses to learn Java 8 and 9 (courses)
Thanks for reading this article so far. If you like these Java 8 Collectors examples, then please share them with your friends and colleagues. If you have any questions or doubt then, please drop a note.

P. S. - If you are looking for some free courses to learn Java then I also suggest you check this list of my favorite free courses to learn Java on Medium. It not only contains courses to learn core java but also essential things like Eclipse, Maven, JUnit, Docker, and other tools needed by Java programmers. 

1 comment:

Feel free to comment, ask questions if you have any doubt.