検索

キーワード


【Java】ランダムな値を生成してみよう!Randomクラスの使い方! java.util.Random

  • 公開日:2020-07-31 15:51:29
  • 最終更新日:2021-01-25 16:39:19
【Java】ランダムな値を生成してみよう!Randomクラスの使い方! java.util.Random



こんにちは。駆け出しプログラマーの松倉です!

ここでは“乱数”について特に「Randomクラス」の使い方、「Mathクラス(randomメソッド)」と「Randomクラス(java.util.Random)」の違いについて紹介・解説します。

プログラミング未経験の方、Javaについて勉強している方、これから勉強したいと思っている方の参考になれば幸いです!

関連記事リンク:【Java】基本的な数値処理!Mathクラスの使い方を解説!【Java】演算子(算術演算子と複合演算子)の使い方【Java】importの宣言方法や役割、static import との違いを解説!


乱数とは

乱数とは人の意思や状況に依存せず、毎回何が出るかわからない数が出す値、つまりランダムな値のことです。

javaではたびたびランダムな値を使う場合があります。

乱数を使う機会として、暗号化処理やシミュレーション、おみくじや計算問題などのゲーム関連のプログラムを作成する際に頻繁に利用されます。

一般的に Javaで乱数を使用する場合、「Mathクラス(randomメソッド)」と「Randomクラス(java.util.Random)」の2つがあります。 


 

Randomクラス(java.util.Random)

Randomクラスは乱数生成用のクラスであり、さまざまな型で乱数を作ることができるクラスです。

取得したい引数の型に応じて、intや longなど様々な型で値を返すことができるメソッドが用意されています。  


Randomクラスでの乱数生成はシード(種)値と呼ばれる値をもとに、乱数ジェネレータから生成されています。

このシードの値が同じであれば、生成される値を予測可能であるため「擬似乱数」と呼ばれます。

Randomクラスは Mathクラスの randomメソッドより高速に処理を行うことが特徴です。


プログラムの実行時に必要に応じて複数の異なる処理を並行して進めるようなマルチ・スレッド環境では、競合が発生してパフォーマンスが低下する可能性があります。

マルチ・スレッド設計が必要な場合、ThreadLocalRandomクラス(java.util.concurrent.ThreadLocalRandom)を使うことで発生する競合をはるかに少なくするやり方があることを覚えておきましょう。


Randomクラスについて理解したところで下記の内容について解説します!

・Mathクラス(randomメソッド)との違い

・乱数を生成する(nextIntメソッド)

・シード(種)を指定した乱数の生成



Mathクラス(randomメソッド)との違い

Mathクラスは乱数生成用のクラスではなく、様々な数値に関する数値処理用のクラスです。

Mathクラスから提供されている 「randomメソッドを使うことで簡単に乱数を生成することができます

randomメソッドは乱数として「0.0~1.0未満」の範囲で double型の値を返します。


randomメソッドは、内部的に Randomクラスのインスタンスをシングルトンで持っているため、インスタンスを作ることなく簡単に使えるのが特徴です。

一方で、複数スレッドから同時に利用されるような場面では、パフォーマンス的な問題が発生する可能性がある事には注意する必要があります。



乱数を生成する(nextIntメソッド)

正の整数で指定範囲の乱数を生成する場合は、Random クラスの 「nextIntメソッド」を使います。


nextIntメソッドの使い方

nextInt(指定値)

このメソッドは命令を実行するたびに0から指定値未満の範囲のint型のランダムな整数が生成されます。

引数無しの場合、32ビット整数 (-2,147,483,648 ~ 2,147,483,647)の範囲で生成されます。

同様に乱数生成用のクラスでは nextLong()や nextBoolean()など様々な型で値を返すことが可能です。  


RandomSample1では、0 ~ 9までの範囲でランダムな整数を生成しています。

実際にコードを確認しましょう。 

import java.util.Random;

public class RandomSample1 {
	public static void main(String[] args) {
		Random rnd = new Random();

		//0~9のランダムな値を表示
		System.out.println(rnd.nextInt(10));
	}
}


 実行結果:

3

範囲内で値が出力されていれば成功です。

実行結果が変化するか何度か試して確認してみましょう。



シード(種)を指定した乱数の生成

Randomクラスはアルゴリズムに沿って、「シード(種)」と呼ばれる値をもとに順番に数字を計算し乱数を生成します。

シード値が分かると生成される値を予測することが出来ることから、本当の意味での乱数ではなく区別して「擬似乱数」と呼ばれます。 

 

シードを指定するには Randomクラスのインスタンス生成時にコンストラクタの引数を long型で指定します。

また、setSeedメソッドを使って引数を long型で指定することでもシードを設定することができます。 

 

引数無しの場合、コンストラクタでは現在時刻(ミリ秒単位)がシードとして使われます。

そのため第三者からのシードが特定されてしまう可能性がある事と、シード値が特定された場合、

生成される乱数が予測可能となる事から、セキュリティ面で脆弱な部分があります。

セキュリティ保護を必要とするアプリケーションで乱数を使用する場合、SecureRandomクラス(java.security.SecureRandom)を使うことで暗号用に強化された乱数を生成するやり方もあることを覚えておきましょう。


RandomSample2では同じシード値を指定した場合と違うシード値を指定した場合の乱数生成を行います。

実際にコードを確認してみましょう。

import java.util.Arrays;
import java.util.Random;

public class RandomSample2 {
	public static void main(String[] args) {
		int[] nums = new int[5];

		// 1回目のランダム値の羅列
		Random rnd1 = new Random(8);
		for (int i = 0; i < 5; i++) {
			nums[i] = rnd1.nextInt();
		}
		System.out.println("1回目" + Arrays.toString(nums));

		// 2回目のランダム値の羅列
		Random rnd2 = new Random(8);
		for (int i = 0; i < 5; i++) {
			nums[i] = rnd2.nextInt();
		}
		System.out.println("2回目" + Arrays.toString(nums));

		// 3回目のランダム値の羅列
		Random rnd3 = new Random(10);
		for (int i = 0; i < 5; i++) {
			nums[i] = rnd3.nextInt();
		}
		System.out.println("3回目" + Arrays.toString(nums));
	}
}

 

実行結果:

1回目[-1158562568, -70013384, -1731337436, 64862043, 858120744]
2回目[-1158562568, -70013384, -1731337436, 64862043, 858120744]
3回目[-1157793070, 1913984760, 1107254586, 1773446580, 254270492]

実行結果を確認すると 1回目と 2回目は同じシード値が指定されているため同じ値の羅列されています。

一方で 3回目は異なるシード値が指定されているため別の値の羅列がされています。

同じシード値を指定することで乱数を再現できることがわかります。   



まとめ

今回は Randomクラスと Mathクラスの違いや Randomクラスの使い方などについて解説しました。

乱数は暗号化処理やシミュレーション、ゲーム関連のプログラムを作成する際によく用いられるメソッドです。

注意点として乱数を生成する場合はシード値について考える必要があります。

単純に簡単な乱数の生成をする場合、シード値について深く考える必要はありません。

作成しているプログラムによってはセキュリティ上シード値の暗号化の必要があることを覚えておきましょう!


関連記事リンク:【Java】基本的な数値処理!Mathクラスの使い方を解説!【Java】演算子(算術演算子と複合演算子)の使い方【Java】importの宣言方法や役割、static import との違いを解説!



【著者】

松倉祥大

はじめまして。フォワードソフト株式会社の松倉です。
システムエンジニアとして働き始めたのが2020年4月です。経験や知識がない状態で入社した私は、フォワードソフトの教育研修で一からプログラミングの勉強をしました。教育研修を卒業後、Javaのプログラミングについて初学者向けの記事を共同で制作しています。
知識や経験はまだまだですが、これからいろんな職場で様々な経験しながら勉強していきたいと思っています。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様