Java for Beginner
675 subscribers
549 photos
156 videos
12 files
842 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Класс Random в Java. Особенности и внутреннее устройство

Генерация случайных чисел — одна из важных задач в программировании, которая находит применение в самых разных областях, начиная от криптографии и заканчивая играми. В Java для этой цели существует класс
Random, который позволяет создавать последовательности псевдослучайных чисел.

Основы работы класса Random

Класс Random в Java предоставляет средства для генерации случайных чисел различного типа: целых чисел, чисел с плавающей точкой, булевых значений и т. д. Этот класс базируется на генераторе псевдослучайных чисел (PRNG, pseudo-random number generator), который использует начальное значение (seed) для создания предсказуемой последовательности чисел, которая выглядит случайной.

Когда создается объект Random без указания начального значения, используется текущее время системы в миллисекундах в качестве seed, что делает каждую последовательность уникальной для каждого запуска программы.
import java.util.Random;

public class RandomExample {
public static void main(String[] args) {
Random random = new Random();
int randomInt = random.nextInt();
System.out.println("Random Integer: " + randomInt);
}
}
Этот код создает объект Random и генерирует случайное целое число.


Внутреннее устройство класса Random

Класс Random реализует линейный конгруэнтный метод (LCG) для генерации псевдослучайных чисел. Этот метод заключается в следующем:

𝑋𝑛+1=(𝑎⋅𝑋𝑛+𝑐) mod  𝑚
где:
Xn — текущее значение (seed).
𝑎 — множитель (multiplier).
𝑐 — приращение (increment).
𝑚 — модуль (modulus).


В Java, значения для a, c и m подобраны таким образом, чтобы генератор обладал хорошими статистическими свойствами и большой длиной периода. На практике это означает, что последовательность чисел, сгенерированных объектом Random, будет выглядеть случайной, хотя на самом деле она полностью детерминирована и повторяема при одинаковом начальном значении.

Пример создания объекта Random с seed:
import java.util.Random;

public class RandomWithSeedExample {
public static void main(String[] args) {
Random random = new Random(42); // Создаем Random с фиксированным seed
int randomInt1 = random.nextInt();
int randomInt2 = random.nextInt();

System.out.println("Random Integer 1: " + randomInt1);
System.out.println("Random Integer 2: " + randomInt2);
}
}
В этом примере при каждом запуске программы будут генерироваться одни и те же числа, так как seed фиксирован.


#Java #Training #Medium #Random
Особенности класса Random

Детерминированность: Класс Random генерирует последовательности чисел, которые можно воспроизвести, если известно начальное значение (seed). Это полезно, например, для тестирования, когда нужно получать одни и те же результаты на каждом запуске программы.
Многопоточность:
Random не является потокобезопасным. При использовании в многопоточной среде возможны конфликты, приводящие к некорректной работе. Для таких случаев лучше использовать ThreadLocalRandom, который оптимизирован для многопоточных приложений.
Период генератора: Период генератора — это максимальная длина последовательности псевдослучайных чисел, прежде чем она начнет повторяться. У
Random достаточно большой период, чтобы его было сложно заметить в реальных приложениях, однако, он все равно существует.

Альтернативы: Существует несколько альтернатив классу Random, такие как SecureRandom, который обеспечивает более высокую степень случайности, и SplittableRandom, который эффективнее в многопоточных сценариях.

Влияние начального значения (seed)

Одной из ключевых особенностей работы с
Random является возможность задания начального значения (seed). Понимание этой концепции важно для ситуаций, когда требуется воспроизводимость экспериментов или процессов.
Фиксированный seed: Если используется фиксированный seed, последовательность случайных чисел всегда будет одинаковой. Это полезно для тестирования, где результаты должны быть предсказуемыми и сравнимыми.
Случайный seed: Когда seed не задан явно, используется текущее время в миллисекундах. Это обеспечивает разнообразие последовательностей чисел при каждом запуске программы, но делает воспроизводимость невозможной без логирования seed.

import java.util.Random;

public class RandomSeedExample {
public static void main(String[] args) {
Random random1 = new Random(12345);
Random random2 = new Random(12345);

System.out.println("Random 1:");
System.out.println(random1.nextInt());
System.out.println(random1.nextInt());

System.out.println("Random 2:");
System.out.println(random2.nextInt());
System.out.println(random2.nextInt());
}
}
В этом примере оба объекта Random генерируют одинаковые числа, так как они используют один и тот же seed.


Недостатки и ограничения

Несмотря на широкое применение, класс Random имеет некоторые ограничения:
Псевдослучайность: Генератор не создает истинно случайных чисел. Для криптографии и других задач, требующих высокой степени случайности, лучше использовать SecureRandom.
Неоптимальность в многопоточности:
Random не оптимизирован для использования в многопоточных приложениях. Если несколько потоков одновременно используют один и тот же объект Random, это может привести к снижению производительности и даже к ошибкам.
Ограниченная функциональность:
Random не предоставляет методов для генерации всех возможных распределений случайных чисел (например, нормального распределения). Для этих целей потребуется использовать дополнительные библиотеки или писать собственную реализацию.

#Java #Training #Medium #Random
Основные методы класса Random, примеры применения

nextInt()
Этот метод генерирует случайное целое число в пределах от Integer.MIN_VALUE до Integer.MAX_VALUE. Он часто используется в различных приложениях, где необходимо случайным образом выбирать индекс массива или генерировать идентификаторы.
import java.util.Random;

public class NextIntExample {
public static void main(String[] args) {
Random random = new Random();
int randomInt = random.nextInt();
System.out.println("Random Integer: " + randomInt);
}
}


nextInt(int bound)
Этот метод возвращает случайное целое число в диапазоне от 0 (включительно) до указанного значения bound (исключительно). Это полезно для выбора случайного элемента из массива или списка фиксированного размера.
import java.util.Random;

public class NextIntBoundExample {
public static void main(String[] args) {
Random random = new Random();
int randomInt = random.nextInt(10); // Генерация числа от 0 до 9
System.out.println("Random Integer (0-9): " + randomInt);
}
}


nextLong()
Метод nextLong() генерирует случайное длинное целое число (тип long) в пределах от Long.MIN_VALUE до Long.MAX_VALUE.
import java.util.Random;

public class NextLongExample {
public static void main(String[] args) {
Random random = new Random();
long randomLong = random.nextLong();
System.out.println("Random Long: " + randomLong);
}
}


nextFloat()
Этот метод возвращает случайное число с плавающей точкой типа float в диапазоне от 0.0 до 1.0 (исключительно). Применяется в ситуациях, когда требуется получить случайное дробное число в пределах фиксированного диапазона.
import java.util.Random;

public class NextFloatExample {
public static void main(String[] args) {
Random random = new Random();
float randomFloat = random.nextFloat();
System.out.println("Random Float: " + randomFloat);
}
}


nextDouble()
Метод nextDouble() аналогичен nextFloat(), но возвращает значение типа double. Он используется для генерации случайных дробных чисел с большей точностью.
import java.util.Random;

public class NextDoubleExample {
public static void main(String[] args) {
Random random = new Random();
double randomDouble = random.nextDouble();
System.out.println("Random Double: " + randomDouble);
}
}


nextBoolean()
Метод nextBoolean() генерирует случайное логическое значение (true или false). Этот метод полезен в ситуациях, когда необходимо принять случайное бинарное решение, например, выбор направления или вариант действия.
import java.util.Random;

public class NextBooleanExample {
public static void main(String[] args) {
Random random = new Random();
boolean randomBoolean = random.nextBoolean();
System.out.println("Random Boolean: " + randomBoolean);
}
}


nextBytes(byte[] bytes)
Метод nextBytes(byte[] bytes) заполняет переданный массив байтов случайными значениями. Это полезно, когда нужно сгенерировать массив случайных байтов, например, для использования в криптографических алгоритмах или для случайной инициализации данных.
import java.util.Random;

public class NextBytesExample {
public static void main(String[] args) {
Random random = new Random();
byte[] randomBytes = new byte[10];
random.nextBytes(randomBytes);

System.out.println("Random Bytes: ");
for (byte b : randomBytes) {
System.out.print(b + " ");
}
}
}


#Java #Training #Medium #Random
Примеры применения методов класса Random

1. Симуляция броска кубика

Представим, что нужно создать программу, которая будет симулировать бросок кубика. Это классическая задача, где необходимо сгенерировать случайное число от 1 до 6.
import java.util.Random;

public class DiceRollSimulation {
public static void main(String[] args) {
Random random = new Random();
int diceRoll = random.nextInt(6) + 1; // Генерация числа от 1 до 6
System.out.println("Dice Roll: " + diceRoll);
}
}
В этом примере мы используем метод nextInt(int bound) с параметром 6, чтобы получить случайное число от 0 до 5, и добавляем 1, чтобы результат был в диапазоне от 1 до 6.


2. Генерация случайного пароля
Допустим, нам нужно сгенерировать случайный пароль длиной 8 символов, состоящий из букв и цифр. Мы можем использовать методы класса Random для этой задачи.
import java.util.Random;

public class PasswordGenerator {
public static void main(String[] args) {
Random random = new Random();
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder password = new StringBuilder();

for (int i = 0; i < 8; i++) {
int index = random.nextInt(characters.length());
password.append(characters.charAt(index));
}

System.out.println("Generated Password: " + password.toString());
}
}
Этот код создает случайный пароль длиной 8 символов, используя метод nextInt(int bound) для выбора случайного индекса символа из строки, содержащей все возможные символы пароля.


3. Симуляция монетки
Если вам нужно смоделировать подбрасывание монетки (где есть только два возможных исхода — орел или решка), можно использовать метод nextBoolean().
import java.util.Random;

public class CoinFlipSimulation {
public static void main(String[] args) {
Random random = new Random();
boolean coinFlip = random.nextBoolean();
if (coinFlip) {
System.out.println("Heads");
} else {
System.out.println("Tails");
}
}
}
В этом примере случайное значение true означает "Орел", а false — "Решка".


4. Случайный выбор из списка
Представьте, что вам нужно случайным образом выбрать элемент из списка, например, случайное имя из списка имен.
import java.util.Random;
import java.util.List;
import java.util.Arrays;

public class RandomNamePicker {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Diana");
Random random = new Random();
String randomName = names.get(random.nextInt(names.size()));

System.out.println("Randomly Picked Name: " + randomName);
}
}
Здесь метод nextInt(int bound) используется для выбора случайного индекса из списка имен.


5. Генерация случайной даты
Если вам нужно сгенерировать случайную дату в определенном диапазоне, можно воспользоваться комбинацией Random и Calendar.
import java.util.Random;
import java.util.Calendar;

public class RandomDateGenerator {
public static void main(String[] args) {
Random random = new Random();
Calendar calendar = Calendar.getInstance();

int year = random.nextInt(2022 - 2000) + 2000; // Год от 2000 до 2021
int dayOfYear = random.nextInt(calendar.getActualMaximum(Calendar.DAY_OF_YEAR)) + 1;

calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.DAY_OF_YEAR, dayOfYear);

System.out.println("Random Date: " + calendar.getTime());
}
}
В этом примере мы генерируем случайную дату между 2000 и 2021 годами, используя случайное число для года и дня года.


#Java #Training #Medium #Random