乱数を生成する方法 Java

⚡ スマートサマリー

乱数 Java これらは、関連する4つの標準ライブラリオプション、Randomクラス、Math.random、ThreadLocalRandom、およびSecureRandomから提供され、それぞれが実際のアプリケーション向けに、速度、スレッドの安全性、および暗号化の強度の異なる組み合わせをカバーしています。

  • 🎲 ランダムクラス: java.util.Random は nextInt、nextLong、next を公開しますDouble、そして一般的なプリミティブ型の場合は nextBoolean です。
  • 🧮 数学.乱数: Math.random は、共有の Random インスタンスを使用して、0.0 を含む 1.0 を含まない double 値を返します。
  • 🎯 カスタム範囲: nextInt に境界値を指定するか、Math.random をスケーリングして、任意の最小値と最大値の範囲内で値を生成します。
  • 🧵 ねじの安全性: java.util.concurrent の ThreadLocalRandom は、各スレッドに独自のジェネレーターを提供し、競合が発生する状況下で共有 Random よりも優れたパフォーマンスを発揮します。
  • 🔐 セキュリティ: java.security の SecureRandom は、パスワード、トークン、セッションキーに対して暗号学的に強力な値を生成します。
  • 🌱 再現性: 固定のlong型で乱数をシードすると、テストやシミュレーションが実行間で決定論的になります。

乱数を生成する方法 Java

乱数はあらゆる場所に表示されます Java単体テストデータやサイコロゲームからセッショントークンやシャッフルされたデッキまで。このチュートリアルでは、乱数を生成する方法を説明します。 Java 標準ライブラリのあらゆるオプションの使い方と、用途に合った適切なオプションの選び方。

乱数を生成する Java

その Java 標準ライブラリには、乱数を生成するための一般的な方法が4つあります。

  • java.util.Random は汎用クラスです。次のようなメソッドを通じて、ブール値、整数値、長整数値、浮動小数点値、倍精度浮動小数点値を生成します。 nextInt, nextLong, nextDouble.
  • Math.random は、共有の 0.0 (含む) から 1.0 (含まない) の間の double を返す静的ヘルパーです。 Random 内部的に。
  • ThreadLocalRandom in java.util.concurrent 各スレッドに独自のジェネレーターを割り当てることで、複数のスレッドが単一のインスタンスを競合しないようにします。
  • SecureRandom in java.security パスワード、セッション識別子、および鍵用の暗号学的に強力な擬似乱数を生成します。

以下のセクションでは、それぞれの方法で10個の乱数を生成する方法を示します。

例: 乱数を生成する Java ランダムクラス

最初の例では java.util.Random 0から99までの範囲の整数を10個生成する:

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 数学ランダム

0.0から1.0の範囲で10個の乱数を生成するには、静的関数を呼び出します。 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までの倍精度浮動小数点数など、特定の範囲内の乱数が必要になることがよくあります。2つのパターンでほぼすべてのケースをカバーできます。

最小値と最大値(両端を含む)の間のランダムな整数:

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値:

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) サイコロを10回振る。

マルチスレッド用の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 (NAIST) と 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 より強力なアルゴリズムと豊富なシードデータを使用しているためです。セキュリティ関連の作業にはこのジェネレーターを使用し、ゲーム、シミュレーション、テストデータにはより高速なジェネレーターを使用してください。

よくあるご質問

java.util.Random インスタンスを作成し、nextInt、nextLong、next を呼び出します。Doubleまたは nextBoolean を使用します。手っ取り早く1行で済ませたい場合は、0.0~1.0 の間の double 値を返す Math.random を使用します。どちらの方法も標準ライブラリに含まれています。

整数の場合は random.nextInt(max – min + 1) + min を、倍精度浮動小数点数の場合は min + (max – min) * Math.random() を呼び出します。これらの式は、ジェネレーターの範囲をターゲットウィンドウに合わせてスケーリングし、最小値分だけシフトします。

Random は、多くのプリミティブ型に対応するメソッドを備え、シード値の設定もサポートする完全なクラスです。Math.random は、0.0 から 1.0 の間の double 値を返す静的ヘルパーです。内部的には、Math.random は単一の共有 Random インスタンスを呼び出します。

はい、しかし同時呼び出しは同じ内部シードを競合するため、スレッドを多用するコードの処理速度が低下します。java.util.concurrent の ThreadLocalRandom.current() を使用して各スレッドに独自のジェネレーターを割り当て、この競合を解消してください。

Randomコンストラクタに固定のlong型値を渡すか(例:new Random(42))、setSeed(42)を呼び出してください。ジェネレータは実行ごとに同じシーケンスを生成するため、再現可能なテストやシミュレーションに不可欠です。

パスワード、セッショントークン、ソルト値、ワンタイムコード、暗号鍵など、予測不可能な値が必要な場合は、SecureRandomを使用してください。Plain Randomは高速ですが予測可能であるため、セキュリティ関連の用途には適していません。

機械学習フレームワークは、擬似乱数発生器を使用して重みを初期化し、トレーニングデータをシャッフルし、検証セットを分割します。シードを固定することで実験の再現性が向上し、チームはモデルの実行結果を比較したり、結果を確実にデバッグしたりできるようになります。

はい。GitHub Copilot は Random、ThreadLocalRandom、SecureRandom のスニペットを生成し、範囲スケーリング式に一致させ、 JUnit テスト。 Rev特にセキュリティに敏感なコードの場合は、選択したクラスがユースケースに適合していることを確認するために、各提案を精査してください。