NextInt: примеры (JAVA)

Метод nextInt в Java: что важно знать
Раздел: Генерация случайных чисел
nextInt(int bound): int

Описание метода nextInt в Java

Метод nextInt предоставляет получение псевдослучайного целого числа и встречается в нескольких реализациях генераторов случайных чисел в Java: java.util.Random, java.security.SecureRandom, java.util.SplittableRandom, java.util.concurrent.ThreadLocalRandom и в API RandomGenerator (Java 17+). Поведение зависит от перегрузки:

  • nextInt() - возвращает случайное значение типа int в полном диапазоне 32-битных знаковых целых: от Integer.MIN_VALUE до Integer.MAX_VALUE включительно.
  • nextInt(int bound) - возвращает случайное целое в диапазоне [0, bound), то есть 0 включительно и bound исключительно. Параметр bound должен быть больше 0, иначе выбрасывается IllegalArgumentException. Распределение равномерное по всем возможным значениям при корректной реализации генератора.
  • В некоторых реализациях (например, ThreadLocalRandom и SplittableRandom) есть перегрузка nextInt(int origin, int bound), возвращающая значение в диапазоне [origin, bound). Требование: origin < bound, иначе выбрасывается IllegalArgumentException.

Возвращаемые значения: целое число int. При использовании без аргумента возможны любые 32-битные значения. При использовании с ограничением - значения в указанном полуоткрытом диапазоне.

Особенности и заметки:

  • Алгоритм генерации у Random определён реализацией в JDK и использует линейный конгруэнтный генератор. Он не криптографически стойкий.
  • SecureRandom использует криптографически стойкий источник, но может быть медленнее.
  • ThreadLocalRandom удобен в многопоточных средах, снижая конкуренцию на общем состоянии.
  • Нельзя предполагать порядок или равномерность между разными реализациями генераторов, если не контролируется конкретная реализация/семя.

Короткие примеры использования

Ниже приведены простые примеры кода со nextInt и возможными результатами. Результаты могут отличаться между версиями Java и запусками, если не задано семя.

1) Полный диапазон

java.util.Random rnd = new java.util.Random(42L);
int x = rnd.nextInt();
System.out.println(x);
Пример вывода: -1170105035

2) Диапазон от 0 до bound-1

java.util.Random rnd = new java.util.Random(42L);
int a = rnd.nextInt(10);
System.out.println(a);
Пример вывода: 5

3) Диапазон с origin и bound (ThreadLocalRandom)

int b = java.util.concurrent.ThreadLocalRandom.current().nextInt(5, 15);
System.out.println(b);
Пример вывода: 12

4) SecureRandom для криптографических нужд

java.security.SecureRandom sr = new java.security.SecureRandom();
int s = sr.nextInt(100);
System.out.println(s);
Пример вывода: 73

Похожие методы в Java и их особенности

  • ThreadLocalRandom.nextInt - подходит для многопоточных программ, уменьшает блокировки и даёт лучшую производительность при параллельном доступе.
  • SplittableRandom.nextInt - эффективен для параллельных алгоритмов и потоков, поддерживает детерминированное разбиение генератора на независимые копии.
  • SecureRandom.nextInt - обеспечивает криптографическую стойкость, рекомендуется для генерации ключей, токенов и секретных кодов; медленнее, чем обычный Random.
  • Random.ints / ThreadLocalRandom.ints - возвращают поток (Stream) случайных чисел с опциями размера и диапазона; удобны для потоковой обработки и генерации батчей.
  • RandomGenerator (Java 17+) - унифицированный интерфейс и набор реализаций (включая быстрое и качественное PRNG), предпочтителен при необходимости гибкого выбора алгоритма.

Аналоги в других языках и отличия

Краткие примеры аналогов и ключевые различия по языкам.

  • JavaScript
  • // Math.random возвращает double в [0,1)
    const n = Math.floor(Math.random() * 10);
    console.log(n);
    Пример вывода: 3

    Для криптостойкости - crypto.getRandomValues, возвращает бинарные данные.

  • Python
  • import random
    print(random.randint(0, 9))  # включает обе границы
    print(random.randrange(0, 10))  # 0..9
    Пример вывода:
    7
    2

    Для криптографии - модуль secrets (например, secrets.randbelow).

  • PHP
  • echo rand(0, 9); // включает обе границы
    echo random_int(0, 9); // криптостойкий
    Пример вывода: 4
  • C#
  • var r = new System.Random(42);
    Console.WriteLine(r.Next());       // 0..Int32.MaxValue-1
    Console.WriteLine(r.Next(10));     // 0..9
    Пример вывода:
    1185267
    5

    Для криптографии - System.Security.Cryptography.RandomNumberGenerator.

  • Go
  • import (
        "fmt"
        "math/rand"
    )
    fmt.Println(rand.Intn(10)) // 0..9
    Пример вывода: 6

    Для криптографии - crypto/rand, работа с байтами.

  • Lua
  • math.randomseed(42)
    print(math.random(0, 9))
    Пример вывода: 8
  • Kotlin
  • val r = kotlin.random.Random(42)
    println(r.nextInt())
    println(r.nextInt(0, 10))
    Пример вывода:
    -1170105035
    5

    Kotlin использует собственный API, но на JVM может делегировать java.util.Random. Есть версии для JavaScript и Native.

  • SQL
  • -- PostgreSQL
    SELECT floor(random() * 10)::int AS n; -- 0..9
    -- MySQL
    SELECT FLOOR(RAND() * 10) AS n;
    Пример вывода: 2

Типичные ошибки при использовании nextInt

  • Передача нулевого или отрицательного bound
  • new java.util.Random().nextInt(0);
    Выброс: java.lang.IllegalArgumentException: bound must be positive
  • Ожидание inclusive верхней границы
  • int v = new java.util.Random().nextInt(10); // возвращается 0..9
    if (v == 10) System.out.println("возможно");
    Никогда не будет 10; распространённая ошибка - off-by-one.
  • Использование java.util.Random для криптографии
  • // НЕКОРРЕКТНО для секретов
    int token = new java.util.Random().nextInt(1_000_000);
    Риск предсказуемости; следует использовать SecureRandom или платформенные крипто-API.
  • Создание нового Random в горячем цикле
  • for (int i=0;i<5;i++){
      java.util.Random r = new java.util.Random();
      System.out.println(r.nextInt(100));
    }
    Пример вывода: часто повторяющиеся или схожие числа при быстром создании, так как сид берётся по времени.
  • Неправильное предположение о равномерности при использовании оператора %
  • // Пытаются взять остаток: может появиться смещение если источник не равномерно делится
    int n = new java.util.Random().nextInt() % 10;
    Результат может быть отрицательным и менее равномерным; рекомендуется nextInt(10).

Изменения и эволюция API

  • В ранних версиях JDK существовал только java.util.Random. Начиная с Java 7–8 появились удобства: поточные методы ints, а в Java 8 - ThreadLocalRandom в JDK 7 и расширения в 8.
  • В Java 17 представлен API RandomGenerator и набор современных реализаций PRNG (JEP 356 и сопутствующие изменения). Это даёт выбор между высокопроизводительными и качественными генераторами вместо единственного LCG из Random.
  • Сам метод Random.nextInt сохраняет совместимость, но при выборе реализации следует учитывать новые классы для улучшения качества или производительности.

Расширенные и редкие сценарии использования

1) Генерация случайного числа в диапазоне [min, max] включительно

Пример java
int min = -5, max = 7;
int v = java.util.concurrent.ThreadLocalRandom.current().nextInt(min, max + 1);
System.out.println(v);
Пример вывода: 3

Пояснение: ThreadLocalRandom поддерживает origin и bound; для включения верхней границы выполняется прибавление 1.

2) Перестановка массива (Fisher-Yates) с использованием nextInt

Пример java
int[] a = {1,2,3,4,5};
java.util.Random rnd = new java.util.Random();
for (int i = a.length - 1; i > 0; i--) {
  int j = rnd.nextInt(i + 1); // 0..i
  int t = a[i]; a[i] = a[j]; a[j] = t;
}
System.out.println(java.util.Arrays.toString(a));
Пример вывода: [3, 5, 1, 4, 2]

Пояснение: корректное использование nextInt(i+1) даёт равновероятную перестановку.

3) Генерация случайного long с использованием nextInt

Пример java
// Составление long из двух int
java.util.Random r = new java.util.Random();
long high = ((long) r.nextInt()) << 32;
long low  = ((long) r.nextInt()) & 0xffffffffL;
long combined = high | low;
System.out.println(combined);
Пример вывода: -4123456789012345678

Пояснение: если требуется случайный 64-битный набор битов и нет nextLong(), можно комбинировать два nextInt().

4) Использование потоков случайных чисел

Пример java
java.util.Random rnd = new java.util.Random(1L);
rnd.ints(5, 0, 100).forEach(System.out::println); // 5 чисел 0..99
Пример вывода:
XX
YY
ZZ
... (примерные значения)

Пояснение: метод ints возвращает IntStream, удобный для функциональной обработки и параллельной генерации.

5) Параллельная генерация без блокировок

Пример java
java.util.stream.IntStream.range(0, 4)
  .parallel()
  .map(i -> java.util.concurrent.ThreadLocalRandom.current().nextInt(100))
  .forEach(System.out::println);
Пример вывода:
12
87
3
44

Пояснение: ThreadLocalRandom уменьшает конкуренцию между потоками при массовой генерации.

6) Репродуцируемые тесты с фиксированным seed

Пример java
java.util.Random r1 = new java.util.Random(123);
java.util.Random r2 = new java.util.Random(123);
System.out.println(r1.nextInt());
System.out.println(r2.nextInt());
Пример вывода:
-1155484576
-1155484576

Пояснение: одинаковое начальное значение даёт одинаковую последовательность, что удобно для модульного тестирования.

7) Комбинация для ограничения смещения (избегание %)

Пример java
// Правильно: равномерное значение 0..n-1
int n = 10;
int x = java.util.concurrent.ThreadLocalRandom.current().nextInt(n);
System.out.println(x);
Пример вывода: 6

Пояснение: использование встроенной перегрузки предотвращает ошибки с модульной операцией и отрицательными значениями.

джава nextInt function comments

En
NextInt Returns a pseudorandom int value between zero (inclusive) and the specified bound (exclusive)