jdk 7の新しい特性ランダム数

3126 ワード

乱数はプログラミング言語の最も基本的な特徴の一つであることはよく知られている.乱数を生成する基本的な方法も同じです.0から1の間の乱数を生成します.簡単そうに見えますが、面白い機能を無視することもあります.
私たちは本から何を学びましたか.
最も明らかなのは、Javaでランダム数を生成する直感的な方法で、簡単な呼び出しだけです.
java.lang.Math.random()
他のすべての言語では、abs、pow、floor、sqrt、その他の数学関数などのMathツールクラスを使用するように、乱数を生成します.多くの人は、書籍、チュートリアル、カリキュラムを通じてこのクラスを理解しています.簡単な例:0.0から1.0までの間で、二重精度浮動小数点数を生成できます.では、上記の情報により、開発者は0.0と10.0の間の二重精度浮動小数点数を生成します.
Math.random() * 10
0と10の間の整数を生成すると、次のように書きます.
Math.round(Math.random() * 10)
ステップアップ
Math.random()のソースコードを読むか、IDEの自動完了機能をいっそ利用することで、開発者はjava.lang.Math.random()が内部のランダム生成オブジェクトを使用していることを簡単に見つけることができます.強力なオブジェクトは、ブール値、すべての数値タイプ、さらにはガウス分布を柔軟にランダムに生成することができます.例:
new java.util.Random().nextInt(10)
オブジェクトであるという欠点があります.その方法は、インスタンスによって呼び出される必要があります.これは、コンストラクション関数を先に呼び出さなければならないことを意味します.メモリが十分な場合、上記の式のように受け入れられます.ただし、メモリが不足すると、問題が発生します.
単純なソリューションでは、乱数を生成するたびに新しいインスタンスを作成することを回避できます.これは、静的クラスを使用することです.java.lang.Mathを思い浮かべたかもしれませんが、私たちはjava.lang.Mathの初期化を改良しています.この工事量は低いですが、間違いがないように簡単なユニットテストをしなければなりません.
プログラムがランダムな数を生成して格納する必要があると仮定すると、問題がまた発生します.たとえば、ステータスを格納し、次の乱数を計算するために内部数を使用するシードを操作または保護する必要がある場合があります.これらの特殊な場合、共用ランダム生成オブジェクトは適切ではありません.
同時
Java EEマルチスレッドアプリケーションの環境では、ランダム生成インスタンスオブジェクトは、静的プロパティとしてクラスまたは他の実装クラスに格納されます.幸いなことに、java.util.Randomはスレッドが安全であるため、複数のスレッド呼び出しがシードを破壊するリスクは存在しない.
もう1つの考慮すべきは、マルチスレッドjava.lang.ThreadLocalの例である.サボるのはJava自体のAPIで単一のインスタンスを実現することです.もちろん、各スレッドに独自のインスタンスオブジェクトがあることを確認することもできます.
Javaはjava.util.Randomの単一インスタンスを管理する良い方法を提供していませんが.しかし、期待されていたJava 7は、乱数を生成する新しい方法を提供した.
java.util.concurrent.ThreadLocalRandom.current().nextInt(10)
この新しいAPIは、Math.random()のように柔軟な単一インスタンス/静的アクセスという他の2つの方法の利点を統合している.ThreadLocalRandomも、他のいかなる処理よりも高い同時性の方法よりも速い.
経験
Chris Marasti-Georg氏は次のように指摘しています.
Math.round(Math.random() * 10)
分散のバランスを崩します.たとえば、0.0~0.4999999で四捨五入を0、0.5~1.4999999で四捨五入を1にします.では、古い文法をどのように使用して正しい均衡分布を実現するかは、次のようになります.
Math.floor(Math.random() * 11)
幸いなことに、java.util.Randomまたはjava.util.concurrent.ThreadLocalRandomを使用すれば、上記の問題を心配する必要はありません.Java実戦プロジェクトではjava.util.Random APIを正しく使用しない危害を紹介しています.この教訓は私たちに使用しないでください.
Math.abs(rnd.nextInt())%n
を使用します.
rnd.nextInt(n)