1. 개요

이 사용방법(예제)에서는 Java에서 난수를 생성하는 다양한 방법을 살펴봅니다.

2. 자바 API 사용

Java API는 목적을 달성할 수 있는 여러 가지 방법을 제공합니다. 그들 중 일부를 보자.

2.1. java.lang.수학

Math 클래스 의 random 메서드는 0.0(포함)에서 1.0(제외) 범위 의 double 값을 반환합니다 . minmax 로 정의된 주어진 범위에서 난수를 얻기 위해 이를 사용하는 방법을 살펴보겠습니다 .

int randomWithMathRandom = (int) ((Math.random() * (max - min)) + min);

2.2. java.util.Random

Java 1.7 이전에 난수를 생성하는 가장 인기 있는 방법은 nextInt 를 사용하는 것이었 습니다. 매개변수를 사용하거나 사용하지 않고 이 방법을 사용하는 두 가지 방법이 있습니다. no-parameter 호출은 거의 동일한 확률 로 모든 int 값을 반환합니다. 따라서 음수를 얻을 가능성이 매우 높습니다.

Random random = new Random();
int randomWithNextInt = random.nextInt();

바인딩된 매개변수와 함께 netxInt 호출을 사용하면 범위 내의 숫자를 얻게 됩니다.

int randomWintNextIntWithinARange = random.nextInt(max - min) + min;

그러면 0(포함)과 매개변수(제외) 사이의 숫자가 제공됩니다. 따라서 바인딩된 매개변수는 0보다 커야 합니다 . 그렇지 않으면 java.lang.IllegalArgumentException 이 발생 합니다.

Java 8은 java.util.stream.IntStream 을 반환하는 새로운 ints 메서드를 도입했습니다.  사용 방법을 살펴보겠습니다.

매개 변수가 없는 ints 메서드는 int무제한 스트림을 반환 합니다.

IntStream unlimitedIntStream = random.ints();

스트림 크기를 제한하기 위해 단일 매개변수를 전달할 수도 있습니다.

IntStream limitedIntStream = random.ints(streamSize);

물론 생성된 범위의 최대값과 최소값을 설정할 수 있습니다.

IntStream limitedIntStreamWithinARange = random.ints(streamSize, min, max);

2.3. java.util.concurrent.ThreadLocalRandom

Java 1.7 릴리스에서는 ThreadLocalRandom 클래스 를 통해 난수를 생성하는 새롭고 보다 효율적인 방법을 제공 했습니다. 이것은 Random 클래스 와 세 가지 중요한 차이점이 있습니다 .

  • ThreadLocalRandom 의 새 인스턴스를 명시적으로 시작할 필요가 없습니다 . 이는 쓸모없는 인스턴스를 많이 생성하고 가비지 수집기 시간을 낭비하는 실수를 방지하는 데 도움이 됩니다.
  • 실제 문제로 이어질 수 있는 ThreadLocalRandom 에 대한 시드를 설정할 수 없습니다 . 시드를 설정해야 하는 경우 이러한 난수 생성 방법을 피해야 합니다.
  • 랜덤 클래스는 다중 스레드 환경에서 잘 수행되지 않습니다 .

이제 어떻게 작동하는지 봅시다:

int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current().nextInt(min, max);

Java 8 이상에서는 새로운 가능성이 있습니다. 첫째, nextInt 메서드에는 두 가지 변형이 있습니다.

int randomWithThreadLocalRandom = ThreadLocalRandom.current().nextInt();
int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current().nextInt(max);

둘째, 더 중요한 것은 ints 메서드를 사용할 수 있다는 것입니다.

IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current().ints();

2.4. java.util.SplittableRandom

Java 8은 또한 매우 빠른 생성기인 SplittableRandom 클래스를 제공합니다.

JavaDoc에서 볼 수 있듯이 이것은 병렬 계산에 사용하기 위한 생성기입니다. 인스턴스가 스레드로부터 안전하지 않다는 것을 아는 것이 중요합니다. 따라서 이 클래스를 사용할 때 주의해야 합니다.

nextIntints 메서드 를 사용할 수 있습니다 . nextInt 를 사용 하면 두 매개변수 호출을 사용하여 상단 및 하단 범위를 직접 설정할 수 있습니다.

SplittableRandom splittableRandom = new SplittableRandom();
int randomWithSplittableRandom = splittableRandom.nextInt(min, max);

이 사용 방법은 max 매개변수가 min 보다 큰지 확인합니다 . 그렇지 않으면 IllegalArgumentException 이 발생 합니다. 그러나 양수 또는 음수로 작업하는지 여부는 확인하지 않습니다. 따라서 모든 매개변수는 음수가 될 수 있습니다. 또한 사용 가능한 1개 및 0개 매개변수 호출이 있습니다. 이전에 설명한 것과 동일한 방식으로 작동합니다.

ints 메서드 도 사용할 수 있습니다. 즉, int의 스트림을 쉽게 얻을 수 있습니다 . 명확히 하기 위해 제한 또는 무제한 스트림을 선택할 수 있습니다. 제한된 스트림의 경우 번호 생성 범위의 상단과 하단을 설정할 수 있습니다.

IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints(streamSize, min, max);

2.5. java.security.SecureRandom

Security에 민감한 애플리케이션이 있는 경우 SecureRandom 사용을 고려해야 합니다. 이것은 암호학적으로 강력한 생성기입니다. 기본 구성 인스턴스는 암호화된 임의 시드를 사용하지 않습니다. 따라서 다음 중 하나를 수행해야 합니다.

  • 시드 설정 — 결과적으로 시드를 예측할 수 없습니다.
  • java.util.secureRandomSeed 시스템 특성을 true 로 설정하십시오.

이 클래스는 java.util.Random 에서 상속됩니다 . 따라서 위에서 본 모든 방법을 사용할 수 있습니다. 예를 들어 int 값을 가져와야 하는 경우 매개 변수 없이 nextInt 를 호출합니다.

SecureRandom secureRandom = new SecureRandom();
int randomWithSecureRandom = secureRandom.nextInt();

반면에 범위를 설정해야 하는 경우 바인딩된 매개변수를 사용하여 범위를 호출할 수 있습니다.

int randomWithSecureRandomWithinARange = secureRandom.nextInt(max - min) + min;

매개변수가 0보다 크지 않으면 IllegalArgumentException 을 발생 시키는 이 방법을 기억해야 합니다 .

3. 타사 API 사용

우리가 본 것처럼 Java는 난수 생성을 위한 많은 클래스와 메서드를 제공합니다. 그러나 이러한 목적을 위한 타사 API도 있습니다.

우리는 그들 중 일부를 살펴볼 것입니다.

3.1. org.apache.commons.math3.random.RandomDataGenerator

Apache Commons 프로젝트의 commons 수학 라이브러리에는 많은 생성기가 있습니다. 가장 쉽고 아마도 가장 유용한 것은 RandomDataGenerator 입니다. 무작위 생성을 위해 Well19937c 알고리즘을 사용합니다 . 그러나 알고리즘 구현을 제공할 수 있습니다.

그것을 사용하는 방법을 보자. 먼저 의존성을 추가해야 합니다.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-math3</artifactId>
    <version>3.6.1</version>
</dependency>

commons-math3 의 최신 버전은 Maven Central 에서 찾을 수 있습니다 .

그런 다음 작업을 시작할 수 있습니다.

RandomDataGenerator randomDataGenerator = new RandomDataGenerator();
int randomWithRandomDataGenerator = randomDataGenerator.nextInt(min, max);

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

확실히 이것은 가장 빠른 난수 생성기 구현 중 하나입니다. 밀라노 대학의 정보 과학부에서 개발되었습니다.

라이브러리는 Maven Central 리포지토리에서도 사용할 수 있습니다. 따라서 의존성을 추가해 보겠습니다.

<dependency>
    <groupId>it.unimi.dsi</groupId>
    <artifactId>dsiutils</artifactId>
    <version>2.6.0</version>
</dependency>

이 생성기는 java.util.Random 에서 상속 합니다. 그러나 JavaDoc 을 살펴보면 이를 사용하는 방법은 nextInt 메서드 를 통해서만 있다는 것을 알 수 있습니다 . 무엇보다 이 방법은 0 및 1 매개변수 호출에서만 사용할 수 있습니다. 다른 호출은 java.util.Random 메소드를 직접 사용합니다.

예를 들어 범위 내에서 랜덤의 숫자를 얻으려면 다음과 같이 작성합니다.

XoRoShiRo128PlusRandom xoroRandom = new XoRoShiRo128PlusRandom();
int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt(max - min) + min;

4. 결론

난수 생성을 구현하는 방법에는 여러 가지가 있습니다. 그러나 최선의 방법은 없습니다. 따라서 우리는 우리의 필요에 가장 적합한 것을 선택해야 합니다.

전체 예제는  GitHub 에서 찾을 수 있습니다 .

Generic footer banner