【Java入門】乱数を重複なしでランダムに生成する方法

本多 農
書いた人 本多 農

こんにちは!侍エンジニア インストラクターの本多です。

Javaでランダムな値が欲しいと思ったことはありませんか?

例えば、おみくじアプリを作ろう!という時です。

人の意思や状況に依存せず、ランダムな値が欲しい!という時は「乱数」を使います。

この記事では、

・乱数とは何か?
・Math.Randomで乱数を生成する方法
・RandomクラスのnextIntメソッドの使い方

という基本的な内容から、

・シード(種)を指定して乱数を発生
・偏りなく乱数を生成する方法
・重複しない乱数を生成する方法

といった応用的な内容に関しても解説していきます。

今回は乱数について、さまざまな方法をわかりやすく解説します!

乱数とは

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

Javaで乱数を使用するには、Java.lang.Mathクラスのrandomメソッドを使う方法とjava.util.Randomクラスを使用するのが一般的です。

Mathクラスのrandomメソッドでは0.0から1.0未満のdouble型の乱数を取得します。

また、Randomクラスはint型やboolean型などさまざまな型で乱数を作ることができます。

Randomクラスでの乱数生成は、シード(種)と呼ばれる値をもとに擬似乱数が生成されます。

擬似乱数とは、プログラミングで生成する乱数に対して使われる用語です。

何が出るか先読みできない本当の意味での乱数と区別して使われます。

シードの値が同じであれば、ランダムな数値が生成されますが、同じ数値の羅列になります。

同じ数値の羅列を再現して出すことができるので本当の意味での乱数ではなく、区別して擬似乱数と呼ばれます。

それでは、乱数の生成について詳しく解説していきます。

Mathクラスのrandomメソッドの使い方

Java.lang.Mathクラスのrandomメソッドを使う方法についてみていきましょう。

randomメソッドは0.0から1.0未満のdouble型の乱数を生成するメソッドです。

実行結果:

範囲を指定して乱数を発生させる方法

int型やlong型などさまざまな型の乱数が場合によっては必要なことがあります。

Mathクラスのrandomメソッドで生成したdouble型の値を、それぞれの型にキャストするなどの方法もありますが、もっと簡単に乱数を取得できる方法があります。

RandomクラスのnextIntメソッドなどを使う方法です。

nextIntメソッドを使うと、int型の乱数を生成することができます。

その他にもlong型やdouble型、float型、boolean型の乱数を生成するメソッドもあります。

それぞれの型を生成するメソッドについて以下の表にまとめました。

メソッド説明
nextIntint型の範囲内でint型の乱数を生成
引数にint型の値を指定すると、
0から指定値未満の範囲のint型の乱数を生成
nextLonglong型の範囲内でlong型の乱数を生成
nextDouble0.0から1.0未満の範囲でdouble型の乱数を生成
nextFloat0.0から1.0未満の範囲でfloat型の乱数を生成
nextBoolean真(true)または偽(false)型の乱数を生成

それでは、生成する値の範囲も指定できるnextIntメソッドの使い方について、サンプルコードで確認しましょう。

実行結果:

このサンプルRandomSample2では、0から10までの整数を生成する、というものになります。

Randomクラスのインスタンスを生成し、それを格納したオブジェクトからnextIntメソッドを呼び出します。

シード(種)を指定して乱数を発生

さきほど、Randomクラスはシード(種)をもとに、擬似乱数を生成すると述べました。

シードを同じにすると同じ乱数の羅列が生成されます。

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

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

サンプルコードで確認しましょう。

実行結果:

このサンプルコードでは、ランダム値の羅列を2回行っています。

2回とも、Randomクラスのインスタンス生成時に同じ値のシードでランダム値を羅列しています。

実行結果を確認すると同じ値が羅列されていることがわかります。

なお、Randomクラスのインスタンス生成時に引数を指定しない場合は、シードには実行時の現在時刻を使用しています。

偏りなく乱数を生成する方法

前章では、Randomクラスを使ってランダムな値を生成する方法について解説してきました。

しかし、Randomクラスを使って生成したランダム値には偏りがあるといわれています。

シードに現在時刻を続けて使って生成した場合や、連続した値を指定して生成した場合は特にです。

それに対して、java.security.SecureRandomクラスを使うことで偏りを減らすことができます。

SecureRandomクラスはシードの素材が予測不可能であることが特徴です。

Randomクラスを使った場合とSecureRandomクラスを使った場合で比較してみましょう。

実行結果:

このサンプルコードでは、RandomクラスとSecureRandomクラスを使って乱数を生成しています。

どちらの場合も、シードには連続した値を使用して生成した値の最小値と最大値を出力表示しています。

Randomクラスの場合、最小値と最大値の値が近く偏りがあることがわかります。

これに対しては、SecureRandomクラスは0.0から1.0未満の範囲内で乱数が生成されていることがわかります。

このようにシード(種)の偏りを減らして乱数を生成したい場合は、SecureRandomクラスを使用することをオススメします。

重複しない乱数を生成する方法

乱数の発生といっても、同じ値が全く出ないという保証はありません。

何度かは同じ値が生成されることがあります。

単純に発生させるだけでは重複は避けられません

重複しない乱数、例えば0から10までの整数を重複なく得るにはどうすればよいでしょうか?

ここでは0から10までの整数を順番にArrayListに格納し、shuffleメソッドを使ってシャッフルし、その結果を取り出すという方法をご紹介します。

実行結果:

単純に順番に表示させただけですが、順番に取り出していけば重複しない値を得ることができます。

実行するたびに、順番が変わって出力表示されます。

ランダムな文字列を生成する方法

Javaでランダムな文字列を生成するためのクラスが、org.apache.commons.lang3には用意されているようです。

RandomStringUtilsクラスです。

randomNumericメソッドを使うと数値の文字列を、randomAlphabeticメソッドを使うとアルファベットの文字列を、randomAsciiメソッドを使うとアスキー文字の文字列を生成することができます。

詳細はこちらのサイトを参照してください。
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/RandomStringUtils.html

まとめ

この記事では乱数を生成する方法を解説しました。

単純に乱数を発生させる、といってもいろいろな方法がありますね。

実数か整数か、どこからどこまでの範囲か、重複を許すかどうか、などなど、、、

もし、乱数を生成させる方法を忘れてしまったら、この記事を思い出してくださいね!

Javaカリキュラム無料公開中!
この記事はJava入門完全攻略ガイド【基礎学習/アプリ開発/仕事獲得】の一部になります。このカリキュラムは、プログラミング入門者が、基礎学習からアプリ開発、さらには仕事獲得まで体系的に学べる内容となっています。

Java学習に必要な情報を一つにまとめていますので効率よくJavaを学ぶことが出来ます。この機会に是非活用していただければと思います。

最短でJavaを習得したい方へ

もし、あなたが、

「難しすぎて学習が全然進まない」
「学習量が膨大でゴールが見えない」
「エラーを解決するのに何日もかかってしまう」

など、プログラミング学習やキャリアに関してお困りであれば、まずは『無料体験レッスン』にお申し込み下さい。

あなたにとって、最適の解決策をご提案させていただきます。

詳しくは下の画像から詳しいサービス内容をご確認ください。

cta_bannar-java1

非常識な結果を出す卒業生多数!

エンジニアキャリア戦略

人気記事セレクション

LINEで送る
Pocket

この記事が気に入ったら
いいね!をしてフォローしよう

最新情報をお届けします

書いた人

本多 農

本多 農

関西在住のITエンジニアです。普通の会社に勤務しながら、侍エンジニアのインストラクター、ライターとして活動しています。