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

Метод ints в Java и примеры работы
Раздел: Генерация случайных чисел
ints: IntStream

Описание метода Random.ints

Метод ints принадлежит классу java.util.Random и возвращает поток примитивов IntStream, наполняемый псевдослучайными целыми числами. Доступны несколько перегрузок, позволяющих получать как бесконечные, так и конечные потоки, а также задавать диапазон генерируемых значений.

Сигнатуры (основные варианты):

  • IntStream ints() - бесконечный поток случайных int в полном диапазоне Integer.MIN_VALUE..Integer.MAX_VALUE.
  • IntStream ints(long streamSize) - конечный поток длины streamSize (если streamSize >= 0), значения в полном диапазоне int.
  • IntStream ints(int randomNumberOrigin, int randomNumberBound) - бесконечный поток в диапазоне [randomNumberOrigin, randomNumberBound), то есть правая граница исключается.
  • IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) - конечный поток длины streamSize с числами из диапазона [randomNumberOrigin, randomNumberBound).

Возвращаемый тип: java.util.stream.IntStream. Потоки ленивы; генерация значений происходит только при выполнении терминальной операции.

Особенности и ограничения:

  • Если указан streamSize меньше нуля, генерируется IllegalArgumentException.
  • Если randomNumberOrigin >= randomNumberBound, генерируется IllegalArgumentException.
  • Диапазон правая граница - исключается. Для включающего диапазона нужно увеличить правую границу на единицу, учитывая опасность переполнения.
  • Метод использует алгоритм генератора псевдослучайных чисел класса Random. Для многопоточных сред чаще используют ThreadLocalRandom или SplittableRandom для лучшей производительности и уменьшения конкуренции.

Короткие практические примеры

Создание 5 случайных чисел (бесконечный поток с ограничением).

import java.util.Random;
import java.util.stream.IntStream;

Random r = new Random();
IntStream s = r.ints().limit(5);
s.forEach(System.out::println);

Возможный результат:

-1155484576
-723955400
1033096058
-1690734402
-49796531

Генерация ровно 4 чисел в диапазоне [0, 10):

Random r = new Random();
int[] a = r.ints(4, 0, 10).toArray();
System.out.println(java.util.Arrays.toString(a));

Возможный результат:

[3, 0, 7, 9]

Генерация 6 чисел во всём диапазоне int:

Random r = new Random();
int[] a = r.ints(6).toArray();
System.out.println(java.util.Arrays.toString(a));

Возможный результат:

[-1472260557, 68467952, -1953477462, 1298491028, -47061400, 2113341997]

Попытка неверного диапазона приведёт к исключению:

new Random().ints(3, 10, 5).findFirst(); // randomNumberOrigin >= randomNumberBound

Результат:

Exception in thread "main" java.lang.IllegalArgumentException: bound must be greater than origin

Похожие варианты в Java и их особенности

  • ThreadLocalRandom.current().ints(...) - специализирован для многопоточных приложений, обеспечивает меньшую конкуренцию и лучшую производительность при параллельной генерации.
  • SplittableRandom.ints(...) - предназначен для параллельных вычислений и деления генератора на независимые части. Часто быстрее и лучше масштабируется в больших потоках.
  • SecureRandom (наследует методы Random) - для криптографически стойкой генерации; медленнее и не рекомендуется для высокопроизводительных нелюбых задач.
  • IntStream.range(…) - не является генератором случайных чисел, но используется для создания последовательностей и индексов, когда требуется детерминированный диапазон.

Когда выбирать: для простых задач подойдёт Random. Для многопоточных ситуаций предпочтение стоит отдать ThreadLocalRandom или SplittableRandom. Для безопасности - SecureRandom.

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

  • Python:
    import random
    # randint(a, b) возвращает включительно
    print([random.randint(0, 9) for _ in range(4)])
    # randrange(0,10) как [0,10)
    print([random.randrange(0, 10) for _ in range(4)])
    
    [3, 0, 7, 9]
    [2, 8, 1, 0]
    
    Отличия: randint включает обе границы; генератор не потокобезопасен, но прост в использовании.
  • JavaScript:
    // Math.random() в [0,1)
    function randInt(min, maxExclusive){
      return Math.floor(Math.random() * (maxExclusive - min)) + min;
    }
    console.log(randInt(0,10));
    
    7
    
    Отличие: нет встроенного метода для целых чисел, нужно масштабировать и округлять; не криптографически стойко.
  • PHP:
    echo random_int(0, 9) . PHP_EOL; // криптографически стойкая
    echo mt_rand(0, 9) . PHP_EOL;    // быстрый псевдослучайный
    
    5
    3
    
    Отличие: есть отдельные функции для крипто и для высокой скорости.
  • C#:
    var rnd = new System.Random();
    Console.WriteLine(rnd.Next(0, 10)); // [0,10)
    
    4
    
    Отличие: метод Next возвращает значение с исключающей правой границей, как в Java.
  • Go:
    import "math/rand"
    fmt.Println(rand.Intn(10)) // 0..9
    
    2
    
    Отличие: простые утилиты в пакете math/rand; криптографически стойкая альтернатива в crypto/rand.
  • Kotlin:
    import kotlin.random.Random
    println(Random.nextInt(0, 10)) // [0,10)
    
    6
    
    Отличие: Kotlin использует свои расширения на базе разных реализаций, поведение ограничений схож с Java.
  • SQL:
    -- Пример MySQL
    SELECT FLOOR(RAND() * 10) AS r; -- 0..9
    
    r
    5
    
    Отличие: SQL-диапазон часто строится через умножение случайного [0,1) и округление; контроль качества распределения и потокобезопасности отличается от языковых генераторов.

Типичные ошибки и примеры

1. Неверный диапазон (origin >= bound).

new java.util.Random().ints(1, 10, 10).findFirst();

Результат:

Exception in thread "main" java.lang.IllegalArgumentException: bound must be greater than origin

2. Отрицательный размер потока.

new java.util.Random().ints(-5).count();

Результат:

Exception in thread "main" java.lang.IllegalArgumentException: streamSize must be non-negative

3. Ожидание включающей правой границы. Частая ошибка - предполагать, что ints(origin, bound) включает bound. Для включающей правой границы нужно указать bound + 1, но важно учитывать переполнение при использовании Integer.MAX_VALUE.

4. Использование бесконечного потока без терминальной операции с ограничением (limit) приведёт к зависанию или бесконечной работе.

5. Проблемы производительности при параллельной генерации с единым экземпляром Random из разных потоков: конкурентный доступ снижает скорость. Для многопоточных сценариев предпочтительны ThreadLocalRandom или SplittableRandom.

Изменения и история

Метод ints введён в Java 8 вместе с потоками Stream API. С тех пор поведение и сигнатуры остались стабильными. Дополнительные улучшения касаются производительности и альтернативных реализаций генераторов (например, SplittableRandom и ThreadLocalRandom), но сам контракт Random.ints не претерпел ломающих изменений.

Для криптографии и специальных задач рекомендованы альтернативные классы; в стандартной библиотеке не появлялось новых перегрузок метода ints после Java 8.

Расширенные и нестандартные применения

1) Заполнение массива примитивными значениями случайного размера и преобразование в список:

Пример java
import java.util.Random;
import java.util.stream.IntStream;

Random r = new Random();
int[] arr = r.ints(10, 0, 100).toArray(); // 10 чисел 0..99
System.out.println(java.util.Arrays.toString(arr));
// Если нужен List:
java.util.List list = IntStream.of(arr).boxed().collect(java.util.stream.Collectors.toList());
System.out.println(list);
[12, 89, 3, 45, 67, 0, 21, 34, 56, 78]
[12, 89, 3, 45, 67, 0, 21, 34, 56, 78]

2) Быстрая генерация уникальных случайных чисел в диапазоне с помощью перемешивания:

Пример java
// Получение k уникальных чисел в 0..n-1
int n = 1000, k = 10;
int[] perm = java.util.stream.IntStream.range(0, n).toArray();
java.util.Random r2 = new java.util.Random();
for (int i = 0; i < k; i++) {
    int j = i + r2.nextInt(n - i);
    int tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp;
}
int[] result = java.util.Arrays.copyOfRange(perm, 0, k);
System.out.println(java.util.Arrays.toString(result));
[473, 2, 987, 10, 55, 601, 18, 320, 91, 777]

3) Использование SecureRandom.ints для криптографически стойких значений:

Пример java
import java.security.SecureRandom;
SecureRandom sr = new SecureRandom();
int[] key = sr.ints(16, 0, 256).toArray(); // байтоподобные значения 0..255
System.out.println(java.util.Arrays.toString(key));
[12, 255, 33, 0, 98, 7, 199, 120, 44, 220, 88, 3, 154, 201, 10, 45]

4) Параллельная генерация и агрегация частот: осторожно с общим Random, лучше использовать тредлокал или SplittableRandom.

Пример java
import java.util.concurrent.ThreadLocalRandom;
int[] histogram = ThreadLocalRandom.current()
        .ints(1_000_000, 0, 100)
        .parallel()
        .boxed()
        .collect(java.util.stream.Collectors.groupingBy(i -> i, java.util.stream.Collectors.summingInt(e -> 1)))
        .entrySet().stream()
        .sorted(java.util.Map.Entry.comparingByKey())
        .mapToInt(e -> e.getValue())
        .toArray();
System.out.println("bins: " + histogram.length);
bins: 100

5) Генерация распределения с нестандартным весом: преобразование равномерного потока в требуемое распределение методом инверсии CDF или через взвешенные выборки.

Пример java
// Простой пример: генерация 0 или 1 с вероятностью p для 1
double p = 0.3;
int[] res = ThreadLocalRandom.current()
        .doubles() // поток double в [0,1)
        .mapToInt(d -> d < p ? 1 : 0)
        .limit(20)
        .toArray();
System.out.println(java.util.Arrays.toString(res));
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

6) Заполнение ByteBuffer или генерирование случайных байтов через IntStream (полезно при подготовке тестовых данных):

Пример java
import java.nio.ByteBuffer;
Random r3 = new Random();
byte[] bytes = r3.ints(16, 0, 256).map(i -> (byte) i).collect(() -> new java.util.ArrayList(), (l, b) -> l.add((byte)b), (l1, l2) -> l1.addAll(l2))
        .stream().collect(java.util.stream.Collectors.toList())
        .stream().mapToInt(Byte::intValue).toArray();
// Проще: r3.ints(16,0,256).collect(...)
System.out.println(java.util.Arrays.toString(bytes));
[12, -1, 33, 0, 98, 7, -57, 120, 44, -36, 88, 3, -102, -55, 10, 45]

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

джава ints function comments

En
Ints Returns an effectively unlimited stream of pseudorandom int values