乱数を生成する方法 Java
⚡ スマートサマリー
乱数 Java これらは、関連する4つの標準ライブラリオプション、Randomクラス、Math.random、ThreadLocalRandom、およびSecureRandomから提供され、それぞれが実際のアプリケーション向けに、速度、スレッドの安全性、および暗号化の強度の異なる組み合わせをカバーしています。
乱数はあらゆる場所に表示されます Java単体テストデータやサイコロゲームからセッショントークンやシャッフルされたデッキまで。このチュートリアルでは、乱数を生成する方法を説明します。 Java 標準ライブラリのあらゆるオプションの使い方と、用途に合った適切なオプションの選び方。
乱数を生成する Java
その Java 標準ライブラリには、乱数を生成するための一般的な方法が4つあります。
java.util.Randomは汎用クラスです。次のようなメソッドを通じて、ブール値、整数値、長整数値、浮動小数点値、倍精度浮動小数点値を生成します。nextInt,nextLong,nextDouble.Math.randomは、共有の 0.0 (含む) から 1.0 (含まない) の間の double を返す静的ヘルパーです。Random内部的に。ThreadLocalRandominjava.util.concurrent各スレッドに独自のジェネレーターを割り当てることで、複数のスレッドが単一のインスタンスを競合しないようにします。SecureRandominjava.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 より強力なアルゴリズムと豊富なシードデータを使用しているためです。セキュリティ関連の作業にはこのジェネレーターを使用し、ゲーム、シミュレーション、テストデータにはより高速なジェネレーターを使用してください。

