Как сгенерировать случайное целое число в заданном диапазоне в Java

Простейшим способом получения целого числа в заданном диапазоне можно считать следующий:
public static int getRandBetween(int min, int max) { return min + new Random().nextInt(max - min + 1);}
Здесь и далее, мы выносим все проверки исходных данных за скобки, предполагая, что минимум всегда меньше максимума, а также величины достаточно далеки от максимального и минимального значения int'а, так что у нас нет проблемы перехода этих границ при проведении арифметических операций.

Использование класса Random


Вообще выше приведено довольно грубое использование класса Random, поскольку оно игнорирует ряд его примечательных возможностей.
В первую очередь -- это возможность задать начальное зерно (seed) для последующей генерации чисел. Наличие зерна позволяет генерировать всегда одинаковую последовательность псевдослучайных чисел, что может быть крайне полезно в целях отладки. Например:
public class RandExample {
static Random random = new Random(0L);
public static void main(String[] args) { for (int i = 0; i < 3; i++) { System.out.println(getRandBetween(1, 100)); } }
public static int getRandBetween(int min, int max) { return min + random.nextInt(max - min + 1); }}
На моей машине каждый перезапуск этой программы выводит в консоль одну и ту же последовательность чисел: 61, 49, 30.
Закончив отладку, можно исключить зерно из кода программы.
Начиная с версии Java 8 класс Random позволяет получить поток (IntStream) псевдослучайных целых для последующей обработки. Например, следующий код будет выводить в консоль псевдослучайные целые числа до тех пор, пока исполнение программы не будет прервано вручную:
random.ints().forEach(System.out::println);
Разумеется, на поток можно наложить ограничения. Например:
random.ints(10).forEach(System.out::println);
выведет в консоль уже всего 10 целых чисел, а
random.ints(10, 1, 11).forEach(System.out::println);
выведет в консоль 10 целых чисел в диапазоне от 1 до 10-ти, что нам и требовалось изначально. Из примера видно, максимум задаётся, как максимально необходимое число + 1, и в документации отмечено, что передаваемая параметром верхняя граница исключается (exclusive).
Аналогично метод doubles() позволяет получить (и ограничить) поток псевдослучайных чисел типа double (DoubleStream).

Многопоточные приложения


Начиная с Java 7 для получения псевдослучайных целых в определённом диапазоне, можно получить отдельный Random для каждого потока:
Random safeRandom = ThreadLocalRandom.current();
Так как если использовать один экземпляр Random для нескольких потоков, на них всех будет приходится одно зерно. Это в силу специфики реализации класса Random может приводить к ухудшению производительности. Решением является использование класса ThreadLocalRandom, который наследует Random со всеми его методами, но не имеет указанной проблемы.

Класс Math


Класс Math имеет метод random(), который возвращает случайный double в диапазоне от 0.0 до 1.0. Это значение вполне можно привести к требуемому диапазону целых, например так:
public static int getRandBetween(int min, int max) { return min + (int)(Math.random() * ((max - min) + 1));}
Однако, следует отметить, что этот метод банально использует nextDouble() отдельного экземпляра Random. И как генератор псевдослучайных чисел ничем особо не интересен.
private static final class RandomNumberGeneratorHolder { static final Random randomNumberGenerator = new Random();}
public static double random() { return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();}