Как сгенерировать случайное число в Java

⚡ Умное резюме

Случайные числа в Java Они берутся из четырех связанных вариантов стандартной библиотеки: класса Random, Math.random, ThreadLocalRandom и SecureRandom, каждый из которых обеспечивает различное сочетание скорости, потокобезопасности и криптографической стойкости для реальных приложений.

  • 🎲 Случайный класс: java.util.Random предоставляет доступ к объектам nextInt, nextLong, next.Doubleа также nextBoolean для распространенных примитивных типов.
  • 🧮 Math.random: Метод Math.random возвращает число типа double в диапазоне от 0.0 включительно до 1.0 включительно, используя общий экземпляр Random.
  • 🎯 Пользовательские диапазоны: Передайте ограничение в nextInt или масштабируйте Math.random, чтобы сгенерировать значения в пределах любого минимального и максимального значений.
  • 🧵 Безопасность резьбы: Функция ThreadLocalRandom из библиотеки java.util.concurrent предоставляет каждому потоку собственный генератор случайных чисел и превосходит по производительности общий генератор случайных чисел при наличии конкуренции.
  • 🔐 Безопасность: Функция SecureRandom из библиотеки java.security генерирует криптографически надежные значения для паролей, токенов и ключей сессии.
  • ???? Воспроизводимость результатов: Использование фиксированного значения long в качестве начального значения для генератора случайных чисел обеспечивает детерминированность тестов и симуляций на протяжении всего запуска.

Как сгенерировать случайное число в Java

Случайные числа встречаются повсюду. JavaОт данных для модульного тестирования и игр с бросанием кубиков до токенов сессии и перемешанных колод. В этом руководстве объясняется, как генерировать случайные числа. Java Использование всех опций стандартной библиотеки и выбор подходящей для конкретной задачи.

Генерация случайного числа в Java

Java Стандартная библиотека предлагает четыре распространенных способа генерации случайного числа:

  • java.util.Random Это универсальный класс. Он возвращает значения типов boolean, int, long, float и double с помощью таких методов, как... nextInt, nextLong и nextDouble.
  • Math.random Это статическая вспомогательная функция, которая возвращает значение типа double от 0.0 (включительно) до 1.0 (исключительно), используя разделяемую переменную. Random внутренне.
  • ThreadLocalRandom in java.util.concurrent Это позволяет каждому потоку иметь собственный генератор, благодаря чему несколько потоков не конкурируют за один экземпляр.
  • SecureRandom in java.security генерирует криптографически стойкие псевдослучайные числа для паролей, идентификаторов сессий и ключей.

В разделах ниже показано, как сгенерировать десять случайных чисел каждым из способов.

Пример: генерация случайного числа с помощью Java Случайный класс

В первом примере используется java.util.Random получить десять целых чисел в диапазоне от 0 до 99 включительно:

import java.util.Random;

public class RandomNumbers {
    public static void main(String[] args) {
        Random objGenerator = new Random();
        for (int iCount = 0; iCount < 10; iCount++) {
            int randomNumber = objGenerator.nextInt(100);
            System.out.println("Random No : " + randomNumber);
        }
    }
}

Выход:

Random No : 17
Random No : 57
Random No : 73
Random No : 48
Random No : 68
Random No : 86
Random No : 34
Random No : 97
Random No : 73
Random No : 18

Экземпляр Random создается как objGenerator, nextInt(int bound) Метод возвращает значение от 0 (включительно) до заданного предела (исключительно), поэтому nextInt(100) возвращает значения от 0 до 99. Для обеспечения воспроизводимости последовательности передайте в конструктор начальное значение, например: new Random(42)Использование одного и того же начального значения всегда приводит к одной и той же последовательности, что полезно в тестах и ​​моделировании.

Пример: Использование Java Math.random

Для генерации десяти случайных значений в диапазоне от 0.0 до 1.0 вызовите статическую функцию. Math.random метод внутри поискаЭто самый быстрый способ получить случайное число типа double без создания объекта-генератора:

public class DemoRandom {
    public static void main(String[] args) {
        for (int xCount = 0; xCount < 10; xCount++) {
            System.out.println(Math.random());
        }
    }
}

Выход:

0.46518450373334297
0.14859851177803485
0.5628391820492477
0.6323378498048606
0.1740198445692248
0.9140544122258946
0.9167350036262347
0.49251219841030147
0.7426056725722353
0.2039418871298877

Под капотом, Math.random создает один статический объект Random при первом использовании и звонках nextDouble Это касается данного случая. Этот единственный общий генератор подходит для демонстраций, но становится узким местом при высокой многопоточной нагрузке, что будет рассмотрено в следующих разделах.

Сгенерировать случайное число в заданном диапазоне

В реальных программах обычно требуется случайное значение в определенном диапазоне, например, целое число от 1 до 6 для броска игральной кости или число с плавающей запятой от 10.0 до 20.0 для моделирования. Два варианта подходят практически для всех случаев.

Случайное целое число в диапазоне от min до max (включительно):

import java.util.Random;

public class RangeDemo {
    public static void main(String[] args) {
        Random rnd = new Random();
        int min = 1;
        int max = 6;
        // nextInt(max - min + 1) returns 0..(max-min), then shift by min
        int dice = rnd.nextInt(max - min + 1) + min;
        System.out.println("Dice roll : " + dice);
    }
}

Случайное число с плавающей запятой в диапазоне от минимального до максимального значения:

double min = 10.0;
double max = 20.0;
double value = min + (max - min) * Math.random();
System.out.println("Value : " + value);

Оба алгоритма работают следующим образом: берут значение из исходного диапазона генератора, масштабируют его до ширины целевого диапазона и сдвигают вверх на минимальное значение. Если вы находитесь на Java В версиях 8 и более поздних можно добиться того же результата и в более новых версиях. ints, longs и doubles потоковые методы на Random, например rnd.ints(10, 1, 7).forEach(System.out::println) за десять бросков кубиков.

ThreadLocalRandom для многопоточности Code

Единый общий Random Является потокобезопасным, но медленным при конкуренции за ресурсы, поскольку каждый поток должен синхронизироваться с одним и тем же внутренним начальным значением. ThreadLocalRandom, добавлено в Java 7 и проживает в java.util.concurrent, это дает каждому потоку свой собственный генератор, поэтому конфликтов блокировок не возникает.

import java.util.concurrent.ThreadLocalRandom;

public class ThreadLocalDemo {
    public static void main(String[] args) {
        // random int in [1, 100]
        int i = ThreadLocalRandom.current().nextInt(1, 101);

        // random long in [1000, 5000]
        long l = ThreadLocalRandom.current().nextLong(1000L, 5001L);

        // random double in [0.0, 1.0)
        double d = ThreadLocalRandom.current().nextDouble();

        System.out.println(i + " " + l + " " + d);
    }
}

Используйте ThreadLocalRandom.current() внутри рабочих потоков, параллельных потоков и любых параллельно выполняемых задач. Обратите внимание, что setSeed бросает UnsupportedOperationExceptionТаким образом, использование генератора случайных чисел для обеспечения воспроизводимости результатов не поддерживается; если вам нужен фиксированный генератор случайных чисел, используйте обычный генератор случайных чисел. Random.

SecureRandom для генерации случайных чисел, имеющих важное значение для безопасности. Numbers

Экземпляры Random и ThreadLocalRandom Они не являются криптографически защищенными. Имея несколько примеров выходных данных, злоумышленник может восстановить внутреннее состояние и предсказать будущие значения. Для паролей, токенов сессии, значений соли и криптографических ключей используйте java.security.SecureRandom Вместо этого он берет исходный материал из пула энтропии операционной системы и выдает значения, которые не поддаются прогнозированию.

import java.security.SecureRandom;

public class SecureDemo {
    public static void main(String[] args) {
        SecureRandom secure = new SecureRandom();

        byte[] token = new byte[16];
        secure.nextBytes(token);          // 128-bit random token

        int otp = secure.nextInt(1_000_000); // 6-digit one-time code

        System.out.println("OTP : " + String.format("%06d", otp));
    }
}

SecureRandom медленнее, чем Random Потому что он использует более мощные алгоритмы и более богатый исходный материал. Используйте его для задач обеспечения безопасности, а более быстрые генераторы — для игр, симуляций и тестовых данных.

Часто задаваемые вопросы (FAQ)

Создайте экземпляр класса java.util.Random и вызовите методы nextInt, nextLong, next.Doubleили nextBoolean. Для быстрого решения в одну строку используйте Math.random, который возвращает значение типа double от 0.0 до 1.0. Оба подхода входят в стандартную библиотеку.

Вызовите random.nextInt(max – min + 1) + min для целых чисел или min + (max – min) * Math.random() для чисел с плавающей запятой. Формулы масштабируют диапазон генератора в соответствии с целевым окном и сдвигают его на минимальное значение.

Random — это полноценный класс с методами для многих примитивных типов и поддержкой инициализации. Math.random — это статический вспомогательный метод, возвращающий значение типа double от 0.0 до 1.0. Внутри Math.random вызывает единственный общий экземпляр класса Random.

Да, но одновременные вызовы конкурируют за один и тот же внутренний генератор случайных чисел, что замедляет работу многопоточного кода. Используйте ThreadLocalRandom.current() из java.util.concurrent, чтобы каждый поток имел свой собственный генератор и устранить эту конкуренцию.

Передайте фиксированное значение типа long в конструктор Random, например, new Random(42), или вызовите setSeed(42). Генератор будет создавать одну и ту же последовательность при каждом запуске, что крайне важно для повторяемых тестов и симуляций.

Используйте SecureRandom всякий раз, когда значение должно быть устойчивым к предсказанию, например, пароли, токены сеансов, значения соли, одноразовые коды и криптографические ключи. Plain Random работает быстро, но предсказуемо, поэтому он небезопасен для задач обеспечения безопасности.

Фреймворки машинного обучения используют псевдослучайные генераторы для инициализации весов, перемешивания обучающих данных и разделения наборов данных для валидации. Фиксированное начальное значение генератора случайных чисел делает эксперименты воспроизводимыми, позволяя командам сравнивать результаты работы моделей и надежно отлаживать ошибки.

Да. GitHub Copilot генерирует фрагменты кода для Random, ThreadLocalRandom и SecureRandom, соответствующие формулам масштабирования диапазона, и JUnit тесты. RevПросмотрите каждое предложение, чтобы убедиться, что выбранный класс соответствует конкретному сценарию использования, особенно для кода, чувствительного к вопросам безопасности.

Подведем итог этой публикации следующим образом: